<template>
  <div class="faq-manager">
    <div class="faq-content">
      <!-- Header -->
      <div class="faq-header">
        <div class="faq-header-title">
          <div class="faq-title-row">
            <h2 class="faq-breadcrumb">
              <button type="button" class="breadcrumb-link" @click="handleNavigateToKbList">
                {{ $t('menu.knowledgeBase') }}
              </button>
              <t-icon name="chevron-right" class="breadcrumb-separator" />
              <t-dropdown
                v-if="knowledgeDropdownOptions.length"
                :options="knowledgeDropdownOptions"
                trigger="click"
                placement="bottom-left"
                @click="handleKnowledgeDropdownSelect"
              >
                <button
                  type="button"
                  class="breadcrumb-link dropdown"
                  :disabled="!props.kbId"
                  @click.stop="handleNavigateToCurrentKB"
                >
                  <span>{{ kbInfo?.name || '--' }}</span>
                  <t-icon name="chevron-down" />
                </button>
              </t-dropdown>
              <button
                v-else
                type="button"
                class="breadcrumb-link"
                :disabled="!props.kbId"
                @click="handleNavigateToCurrentKB"
              >
                {{ kbInfo?.name || '--' }}
              </button>
              <t-icon name="chevron-right" class="breadcrumb-separator" />
              <span class="breadcrumb-current">{{ $t('knowledgeEditor.faq.title') }}</span>
            </h2>
            <t-tooltip :content="$t('knowledgeBase.settings')" placement="top">
              <button
                type="button"
                class="kb-settings-button"
                :disabled="!props.kbId"
                @click="handleOpenKBSettings"
              >
                <t-icon name="setting" size="16px" />
              </button>
            </t-tooltip>
          </div>
          <p class="faq-subtitle">{{ $t('knowledgeEditor.faq.subtitle') }}</p>
        </div>
      </div>

      <!-- 导入进度条（显示在列表页面顶部） -->
      <div v-if="importState.taskId && importState.taskStatus" class="faq-import-progress-bar">
        <div class="progress-bar-content">
          <div class="progress-bar-header">
            <div class="progress-left">
              <t-icon 
                :name="importState.taskStatus.status === 'running' ? 'loading' : 
                       importState.taskStatus.status === 'success' ? 'check-circle' : 
                       importState.taskStatus.status === 'failed' ? 'error-circle' : 'time'"
                size="18px" 
                class="progress-icon"
                :class="{
                  'icon-loading': importState.taskStatus.status === 'running',
                  'icon-success': importState.taskStatus.status === 'success',
                  'icon-error': importState.taskStatus.status === 'failed'
                }"
              />
              <span class="progress-title">
                {{ importState.taskStatus.status === 'running' ? '导入中...' : 
                   importState.taskStatus.status === 'success' ? '导入完成' : 
                   importState.taskStatus.status === 'failed' ? '导入失败' : '等待中...' }}
              </span>
            </div>
            <div class="progress-right">
              <span class="progress-count">
                {{ importState.taskStatus.processed }}/{{ importState.taskStatus.total }} 条
              </span>
              <t-button
                v-if="importState.taskStatus.status === 'success' || importState.taskStatus.status === 'failed'"
                variant="text"
                theme="default"
                size="small"
                class="progress-close-btn"
                @click="handleCloseProgress"
              >
                <t-icon name="close" size="14px" />
              </t-button>
            </div>
          </div>
          <t-progress
            :percentage="importState.taskStatus.progress"
            :status="importState.taskStatus.status === 'failed' ? 'error' : 
                     importState.taskStatus.status === 'success' ? 'success' : 'active'"
            :label="false"
            class="progress-bar"
          />
          <p v-if="importState.taskStatus.error" class="progress-error">
            {{ importState.taskStatus.error }}
          </p>
        </div>
      </div>

      <div class="faq-main">
        <aside class="faq-tag-panel">
          <div class="sidebar-header">
            <div class="sidebar-title">
              <span>{{ $t('knowledgeBase.faqCategoryTitle') }}</span>
              <span class="sidebar-count">({{ sidebarCategoryCount }})</span>
            </div>
            <div class="sidebar-actions">
              <t-button
                size="small"
                variant="text"
                class="create-tag-btn"
                :aria-label="$t('knowledgeBase.tagCreateAction')"
                :title="$t('knowledgeBase.tagCreateAction')"
                @click="startCreateTag"
              >
                <span class="create-tag-plus" aria-hidden="true">+</span>
              </t-button>
            </div>
          </div>
          <div class="tag-search-bar">
            <t-input
              v-model.trim="tagSearchQuery"
              size="small"
              :placeholder="$t('knowledgeBase.tagSearchPlaceholder')"
              clearable
            >
              <template #prefix-icon>
                <t-icon name="search" size="14px" />
              </template>
            </t-input>
          </div>
          <t-loading :loading="tagLoading" size="small">
            <div ref="tagListRef" class="faq-tag-list" @scroll="handleTagListScroll">
              <div
                class="faq-tag-item"
                :class="{ active: selectedTagId === '' }"
                @click="handleUntaggedClick"
              >
                <div class="faq-tag-left">
                  <t-icon name="folder" size="18px" />
                  <span>{{ $t('knowledgeBase.untagged') }}</span>
                </div>
                <span class="faq-tag-count">{{ untaggedFAQCount }}</span>
              </div>

              <div v-if="creatingTag" class="faq-tag-item tag-editing" @click.stop>
                <div class="faq-tag-left">
                  <t-icon name="folder" size="18px" />
                  <div class="tag-edit-input">
                    <t-input
                      ref="newTagInputRef"
                      v-model="newTagName"
                      size="small"
                      :maxlength="40"
                      :placeholder="$t('knowledgeBase.tagNamePlaceholder')"
                      @keydown.enter.stop.prevent="submitCreateTag"
                      @keydown.esc.stop.prevent="cancelCreateTag"
                    />
                  </div>
                </div>
                <div class="tag-inline-actions">
                  <t-button
                    variant="text"
                  theme="default"
                    size="small"
                  class="tag-action-btn confirm"
                    :loading="creatingTagLoading"
                    @click.stop="submitCreateTag"
                  >
                    <t-icon name="check" size="16px" />
                  </t-button>
                <t-button
                  variant="text"
                  theme="default"
                  size="small"
                  class="tag-action-btn cancel"
                  @click.stop="cancelCreateTag"
                >
                    <t-icon name="close" size="16px" />
                  </t-button>
                </div>
              </div>

              <template v-if="filteredTags.length">
                <div
                  v-for="tag in filteredTags"
                  :key="tag.id"
                  class="faq-tag-item"
                  :class="{ active: selectedTagId === tag.id, editing: editingTagId === tag.id }"
                  @click="handleTagRowClick(tag.id)"
                >
                  <div class="faq-tag-left">
                    <t-icon name="folder" size="18px" />
                    <template v-if="editingTagId === tag.id">
                      <div class="tag-edit-input" @click.stop>
                        <t-input
                          :ref="setEditingTagInputRefByTag(tag.id)"
                          v-model="editingTagName"
                          size="small"
                          :maxlength="40"
                          @keydown.enter.stop.prevent="submitEditTag"
                          @keydown.esc.stop.prevent="cancelEditTag"
                        />
                      </div>
                    </template>
                    <template v-else>
                      <span class="tag-name" :title="tag.name">{{ tag.name }}</span>
                    </template>
                  </div>
                  <div class="faq-tag-right">
                    <span class="faq-tag-count">{{ tag.chunk_count || 0 }}</span>
                    <div v-if="editingTagId === tag.id" class="tag-inline-actions" @click.stop>
                      <t-button
                        variant="text"
                        theme="default"
                        size="small"
                        class="tag-action-btn confirm"
                        :loading="editingTagSubmitting"
                        @click.stop="submitEditTag"
                      >
                        <t-icon name="check" size="16px" />
                      </t-button>
                      <t-button
                        variant="text"
                        theme="default"
                        size="small"
                        class="tag-action-btn cancel"
                        @click.stop="cancelEditTag"
                      >
                        <t-icon name="close" size="16px" />
                      </t-button>
                    </div>
                    <div v-else class="tag-more" @click.stop>
                      <t-popup trigger="click" placement="top-right" overlayClassName="tag-more-popup">
                        <div class="tag-more-btn">
                          <t-icon name="more" size="14px" />
                        </div>
                        <template #content>
                          <div class="tag-menu">
                            <div class="tag-menu-item" @click="startEditTag(tag)">
                              <t-icon class="menu-icon" name="edit" />
                              <span>{{ $t('knowledgeBase.tagEditAction') }}</span>
                            </div>
                            <div class="tag-menu-item danger" @click="confirmDeleteTag(tag)">
                              <t-icon class="menu-icon" name="delete" />
                              <span>{{ $t('knowledgeBase.tagDeleteAction') }}</span>
                            </div>
                          </div>
                        </template>
                      </t-popup>
                    </div>
                  </div>
                </div>
              </template>
              <div v-else class="tag-empty-state">
                {{ $t('knowledgeBase.tagEmptyResult') }}
              </div>
              <div v-if="tagLoadingMore" class="tag-loading-more">
                <t-loading size="small" />
              </div>
            </div>
          </t-loading>
        </aside>

        <div class="faq-card-area">
          <!-- 搜索栏 -->
          <div class="faq-search-bar">
            <t-input
              v-model.trim="entrySearchKeyword"
              :placeholder="$t('knowledgeEditor.faq.searchPlaceholder')"
              clearable
              @clear="loadEntries()"
              @keydown.enter="loadEntries()"
            >
              <template #prefix-icon>
                <t-icon name="search" size="16px" />
              </template>
            </t-input>
          </div>
          <!-- Card List Container with Scroll -->
          <div ref="scrollContainer" class="faq-scroll-container" @scroll="handleScroll">
          <t-loading :loading="loading && entries.length === 0" size="medium">
            <!-- Card List -->
            <template v-if="entries.length > 0">
              <div ref="cardListRef" class="faq-card-list">
                <div
                  v-for="entry in entries"
                  :key="entry.id"
                  class="faq-card"
                  :class="{ 'selected': selectedRowKeys.includes(entry.id) }"
                  @click="handleCardSelect(entry.id, !selectedRowKeys.includes(entry.id))"
                >
                  <!-- Card Header -->
                  <div class="faq-card-header">
                    <div class="faq-header-top">
                      <div class="faq-question" :title="entry.standard_question">
                        {{ entry.standard_question }}
                      </div>
                      <div class="faq-card-actions">
                        <t-popup
                          v-model="entry.showMore"
                          overlayClassName="faq-card-popup"
                          trigger="click"
                          destroy-on-close
                          placement="bottom-right"
                          @visible-change="(visible: boolean) => (entry.showMore = visible)"
                        >
                          <div class="card-more-btn" @click.stop>
                            <img class="more-icon" src="@/assets/img/more.png" alt="" />
                          </div>
                          <template #content>
                            <div class="card-menu" @click.stop>
                              <div class="card-menu-item" @click.stop="handleMenuEdit(entry)">
                                <t-icon class="menu-icon" name="edit" />
                                <span>{{ $t('common.edit') }}</span>
                              </div>
                              <div class="card-menu-item danger" @click.stop="handleMenuDelete(entry)">
                                <t-icon class="menu-icon" name="delete" />
                                <span>{{ $t('common.delete') }}</span>
                              </div>
                            </div>
                          </template>
                        </t-popup>
                      </div>
                    </div>
                  </div>

                  <!-- Card Body -->
                  <div class="faq-card-body">
                    <!-- Similar Questions Section -->
                    <div v-if="entry.similar_questions?.length" class="faq-section similar">
                      <div
                        class="faq-section-label clickable"
                        @click.stop="entry.similarCollapsed = !entry.similarCollapsed"
                      >
                        <span>{{ $t('knowledgeEditor.faq.similarQuestions') }}</span>
                        <span class="section-count">
                          ({{ entry.similar_questions.length }})
                        </span>
                        <t-icon
                          :name="entry.similarCollapsed ? 'chevron-right' : 'chevron-down'"
                          class="collapse-icon"
                        />
                      </div>
                      <Transition name="slide-down">
                        <div v-if="!entry.similarCollapsed" class="faq-tags">
                          <FAQTagTooltip
                            v-for="question in entry.similar_questions"
                            :key="question"
                            :content="question"
                            type="similar"
                            placement="top"
                          >
                            <t-tag
                              size="small"
                              variant="light-outline"
                              class="question-tag"
                            >
                              {{ question }}
                            </t-tag>
                          </FAQTagTooltip>
                        </div>
                      </Transition>
                    </div>

                    <!-- Negative Questions Section -->
                    <div v-if="entry.negative_questions?.length" class="faq-section negative">
                      <div
                        class="faq-section-label clickable"
                        @click.stop="entry.negativeCollapsed = !entry.negativeCollapsed"
                      >
                        <span>{{ $t('knowledgeEditor.faq.negativeQuestions') }}</span>
                        <span class="section-count">
                          ({{ entry.negative_questions.length }})
                        </span>
                        <t-icon
                          :name="entry.negativeCollapsed ? 'chevron-right' : 'chevron-down'"
                          class="collapse-icon"
                        />
                      </div>
                      <Transition name="slide-down">
                        <div v-if="!entry.negativeCollapsed" class="faq-tags">
                          <FAQTagTooltip
                            v-for="question in entry.negative_questions"
                            :key="question"
                            :content="question"
                            type="negative"
                            placement="top"
                          >
                            <t-tag
                              size="small"
                              theme="warning"
                              variant="light-outline"
                              class="question-tag"
                            >
                              {{ question }}
                            </t-tag>
                          </FAQTagTooltip>
                        </div>
                      </Transition>
                    </div>

                    <!-- Answers Section -->
                    <div class="faq-section answers">
                      <div
                        class="faq-section-label clickable"
                        @click.stop="entry.answersCollapsed = !entry.answersCollapsed"
                      >
                        <span>{{ $t('knowledgeEditor.faq.answers') }}</span>
                        <span v-if="entry.answers?.length" class="section-count">
                          ({{ entry.answers.length }})
                        </span>
                        <t-icon
                          :name="entry.answersCollapsed ? 'chevron-right' : 'chevron-down'"
                          class="collapse-icon"
                        />
                      </div>
                      <Transition name="slide-down">
                        <div v-if="!entry.answersCollapsed" class="faq-tags">
                          <FAQTagTooltip
                            v-for="answer in entry.answers"
                            :key="answer"
                            :content="answer"
                            type="answer"
                            placement="top"
                          >
                            <t-tag
                              size="small"
                              theme="success"
                              variant="light-outline"
                              class="question-tag"
                            >
                              {{ answer }}
                            </t-tag>
                          </FAQTagTooltip>
                        </div>
                      </Transition>
                    </div>
                  </div>

                  <!-- Card Footer -->
                  <div class="faq-card-footer">
                    <div class="faq-card-tag" @click.stop>
                      <template v-if="tagList.length">
                        <t-dropdown
                          :options="tagDropdownOptions"
                          trigger="click"
                          @click="(data: any) => handleEntryTagChange(entry.id, data.value as string)"
                        >
                          <t-tag size="small" variant="light-outline" class="faq-tag-chip">
                            <span class="tag-text">{{ getTagName(entry.tag_id) || $t('knowledgeBase.untagged') }}</span>
                          </t-tag>
                        </t-dropdown>
                      </template>
                      <template v-else>
                        <t-tag size="small" variant="light-outline" class="faq-tag-chip">
                          <span class="tag-text">{{ getTagName(entry.tag_id) || $t('knowledgeBase.untagged') }}</span>
                        </t-tag>
                      </template>
                    </div>
                    <div class="faq-card-status" @click.stop>
                      <t-tooltip
                        :content="entry.is_enabled ? $t('knowledgeEditor.faq.statusEnabled') : $t('knowledgeEditor.faq.statusDisabled')"
                        placement="top"
                      >
                        <div class="status-item-compact">
                          <t-switch
                            :key="`${entry.id}-${entry.is_enabled}`"
                            size="small"
                            :value="entry.is_enabled"
                            :loading="!!entryStatusLoading[entry.id]"
                            :disabled="!!entryStatusLoading[entry.id]"
                            @click.stop
                            @change="(value: boolean) => handleEntryStatusChange(entry, value)"
                          />
                        </div>
                      </t-tooltip>
                    </div>
                  </div>
                </div>
              </div>
            </template>
            <template v-else>
              <div v-if="!loading" class="faq-empty-state">
                <div class="empty-content">
                  <t-icon name="file-add" size="48px" class="empty-icon" />
                  <div class="empty-text">{{ $t('knowledgeEditor.faq.emptyTitle') }}</div>
                  <div class="empty-desc">{{ $t('knowledgeEditor.faq.emptyDesc') }}</div>
                </div>
              </div>
            </template>
          </t-loading>
          <div v-if="loadingMore" class="faq-load-more">
            <t-loading size="small" :text="$t('common.loading')" />
          </div>
          <div v-if="hasMore === false && entries.length > 0" class="faq-no-more">
            {{ $t('common.noMoreData') }}
          </div>
          </div>
        </div>
      </div>
    </div>
    <!-- Editor Drawer -->
    <t-drawer
      v-model:visible="editorVisible"
      :header="editorMode === 'create' ? $t('knowledgeEditor.faq.editorCreate') : $t('knowledgeEditor.faq.editorEdit')"
      :close-btn="true"
      size="520px"
      placement="right"
      class="faq-editor-drawer"
      @close="handleEditorClose"
    >
      <div class="faq-editor-drawer-content">
        <t-form
          ref="editorFormRef"
          :data="editorForm"
          :rules="editorRules"
          layout="vertical"
          :label-width="0"
          class="faq-editor-form"
        >
          <div class="settings-group">
            <!-- 标准问 -->
            <div class="setting-row vertical setting-row-primary">
              <div class="setting-info">
                <label class="required-label">
                  {{ $t('knowledgeEditor.faq.standardQuestion') }}
                  <span class="required-mark">*</span>
                </label>
                <p class="desc">{{ $t('knowledgeEditor.faq.standardQuestionDesc') }}</p>
              </div>
              <div class="setting-control">
                <t-input 
                  v-model="editorForm.standard_question" 
                  :maxlength="200"
                  class="full-width-input"
                />
              </div>
            </div>

            <!-- 相似问 -->
            <div class="setting-row vertical setting-row-optional setting-row-similar">
              <div class="setting-info">
                <label class="optional-label">{{ $t('knowledgeEditor.faq.similarQuestions') }}</label>
                <p class="desc optional-desc">{{ $t('knowledgeEditor.faq.similarQuestionsDesc') }}</p>
              </div>
              <div class="setting-control">
                <div class="full-width-input-wrapper">
                  <t-input
                    v-model="similarInput"
                    :placeholder="$t('knowledgeEditor.faq.similarPlaceholder')"
                    @keydown.enter.prevent="addSimilar"
                    class="full-width-input"
                  />
                  <t-button
                    theme="primary"
                    variant="outline"
                    :disabled="!similarInput.trim() || editorForm.similar_questions.length >= 10"
                    @click="addSimilar"
                    class="add-item-btn"
                    size="small"
                  >
                    <t-icon name="add" size="16px" />
                  </t-button>
                </div>
                <div v-if="editorForm.similar_questions.length > 0" class="item-list">
                  <div
                    v-for="(question, index) in editorForm.similar_questions"
                    :key="index"
                    class="item-row"
                  >
                    <div class="item-content">{{ question }}</div>
                    <t-button
                      theme="default"
                      variant="text"
                      size="small"
                      @click="removeSimilar(index)"
                      class="remove-item-btn"
                    >
                      <t-icon name="close" size="16px" />
                    </t-button>
                  </div>
                </div>
              </div>
            </div>

            <!-- 反例 -->
            <div class="setting-row vertical setting-row-optional setting-row-negative">
              <div class="setting-info">
                <label class="optional-label">{{ $t('knowledgeEditor.faq.negativeQuestions') }}</label>
                <p class="desc optional-desc">{{ $t('knowledgeEditor.faq.negativeQuestionsDesc') }}</p>
              </div>
              <div class="setting-control">
                <div class="full-width-input-wrapper">
                  <t-input
                    v-model="negativeInput"
                    :placeholder="$t('knowledgeEditor.faq.negativePlaceholder')"
                    @keydown.enter.prevent="addNegative"
                    class="full-width-input"
                  />
                  <t-button
                    theme="primary"
                    variant="outline"
                    :disabled="!negativeInput.trim() || editorForm.negative_questions.length >= 10"
                    @click="addNegative"
                    class="add-item-btn"
                    size="small"
                  >
                    <t-icon name="add" size="16px" />
                  </t-button>
                </div>
                <div v-if="editorForm.negative_questions.length > 0" class="item-list">
                  <div
                    v-for="(question, index) in editorForm.negative_questions"
                    :key="index"
                    class="item-row negative"
                  >
                    <div class="item-content">{{ question }}</div>
                    <t-button
                      theme="default"
                      variant="text"
                      size="small"
                      @click="removeNegative(index)"
                      class="remove-item-btn"
                    >
                      <t-icon name="close" size="16px" />
                    </t-button>
                  </div>
                </div>
              </div>
            </div>

            <!-- 答案 -->
            <div class="setting-row vertical setting-row-primary setting-row-answer">
              <div class="setting-info">
                <label class="required-label">
                  {{ $t('knowledgeEditor.faq.answers') }}
                  <span class="required-mark">*</span>
                </label>
                <p class="desc">{{ $t('knowledgeEditor.faq.answersDesc') }}</p>
              </div>
              <div class="setting-control">
                <div class="textarea-container">
                  <div class="full-width-input-wrapper textarea-wrapper">
                    <t-textarea
                      v-model="answerInput"
                      :placeholder="$t('knowledgeEditor.faq.answerPlaceholder')"
                      :autosize="{ minRows: 3, maxRows: 6 }"
                      class="full-width-textarea"
                      @keydown.ctrl.enter="addAnswer"
                      @keydown.meta.enter="addAnswer"
                    />
                    <t-button
                      theme="primary"
                      variant="outline"
                      :disabled="!answerInput.trim() || editorForm.answers.length >= 5"
                      @click="addAnswer"
                      class="add-item-btn"
                      size="small"
                    >
                      <t-icon name="add" size="16px" />
                    </t-button>
                  </div>
                  <div class="item-count">{{ editorForm.answers.length }}/5</div>
                </div>
                <div v-if="editorForm.answers.length > 0" class="item-list">
                  <div
                    v-for="(answer, index) in editorForm.answers"
                    :key="index"
                    class="item-row answer-row"
                  >
                    <div class="item-content">{{ answer }}</div>
                    <t-button
                      theme="default"
                      variant="text"
                      size="small"
                      @click="removeAnswer(index)"
                      class="remove-item-btn"
                    >
                      <t-icon name="close" size="16px" />
                    </t-button>
                  </div>
                </div>
              </div>
            </div>

            <div class="setting-row vertical">
              <div class="setting-info">
                <label>{{ $t('knowledgeBase.category') || '分类' }}</label>
                <p class="desc">{{ $t('knowledgeEditor.faq.tagDesc') || '为 FAQ 条目选择分类' }}</p>
              </div>
              <div class="setting-control">
                <t-select
                  v-model="editorForm.tag_id"
                  class="full-width-input"
                  :options="tagSelectOptions"
                  clearable
                  :placeholder="$t('knowledgeEditor.faq.tagPlaceholder') || '选择分类'"
                />
              </div>
            </div>
          </div>
        </t-form>
      </div>

      <template #footer>
        <div class="faq-editor-drawer-footer">
          <t-button theme="default" variant="outline" @click="editorVisible = false">
            {{ $t('common.cancel') }}
          </t-button>
          <t-button theme="primary" @click="handleSubmitEntry" :loading="savingEntry">
            {{ editorMode === 'create' ? $t('knowledgeEditor.faq.editorCreate') : $t('common.save') }}
          </t-button>
        </div>
      </template>
    </t-drawer>

    <!-- Import Dialog -->
    <Teleport to="body">
      <Transition name="modal">
        <div v-if="importVisible" class="faq-import-overlay" @click.self="importVisible = false">
          <div class="faq-import-modal">
            <!-- 关闭按钮 -->
            <button class="close-btn" @click="importVisible = false" :aria-label="$t('general.close')">
              <svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor">
                <path d="M15 5L5 15M5 5L15 15" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
              </svg>
            </button>

            <div class="faq-import-container">
              <div class="faq-import-header">
                <h2 class="import-title">{{ $t('knowledgeEditor.faqImport.title') }}</h2>
              </div>

              <div class="faq-import-content">
                <!-- 导入模式选择 -->
                <div class="import-form-item">
                  <label class="import-form-label required">{{ $t('knowledgeEditor.faqImport.modeLabel') }}</label>
                  <t-radio-group v-model="importState.mode" class="import-radio-group">
                    <t-radio-button value="append">{{ $t('knowledgeEditor.faqImport.appendMode') }}</t-radio-button>
                    <t-radio-button value="replace">{{ $t('knowledgeEditor.faqImport.replaceMode') }}</t-radio-button>
                  </t-radio-group>
                </div>

                <!-- 文件上传区域 -->
                <div class="import-form-item">
                  <div class="file-label-row">
                    <label class="import-form-label required">{{ $t('knowledgeEditor.faqImport.fileLabel') }}</label>
                    <t-dropdown
                      :options="downloadExampleOptions"
                      placement="bottom-right"
                      trigger="click"
                      @click="handleDownloadExample"
                      class="download-example-dropdown"
                    >
                      <t-button theme="default" variant="outline" size="small" class="download-example-btn">
                        <t-icon name="download" size="16px" />
                        <span>{{ $t('knowledgeEditor.faqImport.downloadExample') }}</span>
                      </t-button>
                    </t-dropdown>
                  </div>
                  <div class="file-upload-wrapper">
                    <input
                      ref="fileInputRef"
                      type="file"
                      accept=".json,.csv,.xlsx,.xls"
                      @change="handleFileChange"
                      class="file-input-hidden"
                    />
                    <div
                      class="file-upload-area"
                      :class="{ 'has-file': importState.file }"
                      @click="fileInputRef?.click()"
                      @dragover.prevent
                      @dragenter.prevent
                      @drop.prevent="handleFileDrop"
                    >
                      <div class="file-upload-content">
                        <t-icon name="upload" size="32px" class="upload-icon" />
                        <div class="upload-text">
                          <span v-if="!importState.file" class="upload-primary-text">
                            {{ $t('knowledgeEditor.faqImport.clickToUpload') }}
                          </span>
                          <span v-else class="upload-file-name">
                            {{ importState.file.name }}
                          </span>
                          <span v-if="!importState.file" class="upload-secondary-text">
                            {{ $t('knowledgeEditor.faqImport.dragDropTip') }}
                          </span>
                        </div>
                      </div>
                    </div>
                    <p class="import-form-tip">{{ $t('knowledgeEditor.faqImport.fileTip') }}</p>
                  </div>
                </div>

                <!-- 预览区域 -->
                <div v-if="importState.preview.length" class="import-preview">
                  <div class="preview-header">
                    <t-icon name="file-view" size="16px" class="preview-icon" />
                    <span class="preview-title">
                      {{ $t('knowledgeEditor.faqImport.previewCount', { count: importState.preview.length }) }}
                    </span>
                  </div>
                  <div class="preview-list">
                    <div
                      v-for="(item, index) in importState.preview.slice(0, 5)"
                      :key="index"
                      class="preview-item"
                    >
                      <span class="preview-index">{{ index + 1 }}</span>
                      <span class="preview-question">{{ item.standard_question }}</span>
                    </div>
                  </div>
                  <p v-if="importState.preview.length > 5" class="preview-more">
                    {{ $t('knowledgeEditor.faqImport.previewMore', { count: importState.preview.length - 5 }) }}
                  </p>
                </div>

              </div>

              <div class="faq-import-footer">
                <t-button 
                  theme="default" 
                  variant="outline" 
                  @click="handleCancelImport"
                  :disabled="importState.importing && importState.taskStatus?.status === 'running'"
                >
                  {{ $t('common.cancel') }}
                </t-button>
                <t-button 
                  theme="primary" 
                  @click="handleImport" 
                  :loading="importState.importing && !importState.taskId"
                  :disabled="importState.taskStatus?.status === 'running'"
                >
                  {{ importState.taskStatus?.status === 'success' ? $t('common.close') : 
                     importState.taskStatus?.status === 'failed' ? '重试' :
                     $t('knowledgeEditor.faqImport.importButton') }}
                </t-button>
              </div>
            </div>
          </div>
        </div>
      </Transition>
    </Teleport>

    <!-- Batch Tag Dialog -->
    <Teleport to="body">
      <Transition name="modal">
        <div v-if="batchTagDialogVisible" class="batch-tag-overlay" @click.self="batchTagDialogVisible = false">
          <div class="batch-tag-modal">
            <!-- 关闭按钮 -->
            <button class="batch-tag-close-btn" @click="batchTagDialogVisible = false" :aria-label="$t('general.close')">
              <svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor">
                <path d="M15 5L5 15M5 5L15 15" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
              </svg>
            </button>

            <div class="batch-tag-container">
              <div class="batch-tag-header">
                <h2 class="batch-tag-title">{{ $t('knowledgeEditor.faq.batchUpdateTag') }}</h2>
              </div>

              <div class="batch-tag-content">
                <div class="batch-tag-tip">
                  <t-icon name="info-circle" size="16px" class="tip-icon" />
                  <span>{{ $t('knowledgeEditor.faq.batchUpdateTagTip', { count: selectedRowKeys.length }) }}</span>
                </div>
                <t-form layout="vertical" class="batch-tag-form">
                  <t-form-item :label="$t('knowledgeBase.tagLabel')">
                    <t-select
                      v-model="batchTagValue"
                      :options="tagSelectOptions"
                      :placeholder="$t('knowledgeBase.tagPlaceholder')"
                      clearable
                      filterable
                      class="batch-tag-select"
                    >
                      <template #empty>
                        <div class="tag-select-empty">
                          {{ $t('knowledgeBase.noTags') }}
                        </div>
                      </template>
                    </t-select>
                  </t-form-item>
                </t-form>
              </div>

              <div class="batch-tag-footer">
                <t-button 
                  theme="default" 
                  variant="outline" 
                  @click="batchTagDialogVisible = false"
                >
                  {{ $t('common.cancel') }}
                </t-button>
                <t-button 
                  theme="primary" 
                  @click="handleBatchTag"
                >
                  {{ $t('common.confirm') }}
                </t-button>
              </div>
            </div>
          </div>
        </div>
      </Transition>
    </Teleport>

    <!-- Search Test Drawer -->
    <t-drawer
      v-model:visible="searchDrawerVisible"
      :header="$t('knowledgeEditor.faq.searchTestTitle')"
      :close-btn="true"
      size="420px"
      placement="right"
      class="faq-search-drawer"
    >
      <div class="search-test-content">
        <t-form layout="vertical" class="search-form" :label-width="0">
          <div class="settings-group">
            <!-- 查询文本 -->
            <div class="setting-row vertical search-first-row">
              <div class="setting-info">
                <label>{{ $t('knowledgeEditor.faq.queryLabel') }}</label>
                <p class="desc">{{ $t('knowledgeEditor.faq.queryPlaceholder') }}</p>
              </div>
              <div class="setting-control">
                <t-input
                  v-model="searchForm.query"
                  :placeholder="$t('knowledgeEditor.faq.queryPlaceholder')"
                  @keydown.enter.prevent="handleSearch"
                  class="full-width-input"
                />
              </div>
            </div>

            <!-- 相似度阈值 -->
            <div class="setting-row vertical">
              <div class="setting-info">
                <label>{{ $t('knowledgeEditor.faq.similarityThresholdLabel') }}</label>
                <p class="desc">{{ $t('knowledgeEditor.faq.vectorThresholdDesc') }}</p>
              </div>
              <div class="setting-control">
                <div class="slider-wrapper">
                  <t-slider
                    v-model="searchForm.vectorThreshold"
                    :min="0"
                    :max="1"
                    :step="0.1"
                    :show-tooltip="true"
                    :format-tooltip="(val: number) => val.toFixed(2)"
                  />
                  <div class="slider-value">{{ searchForm.vectorThreshold.toFixed(2) }}</div>
                </div>
              </div>
            </div>

            <!-- 匹配数量 -->
            <div class="setting-row vertical">
              <div class="setting-info">
                <label>{{ $t('knowledgeEditor.faq.matchCountLabel') }}</label>
                <p class="desc">{{ $t('knowledgeEditor.faq.matchCountDesc') }}</p>
              </div>
              <div class="setting-control">
                <div class="slider-wrapper">
                  <t-slider
                    v-model="searchForm.matchCount"
                    :min="1"
                    :max="50"
                    :step="1"
                    :show-tooltip="true"
                  />
                  <div class="slider-value">{{ searchForm.matchCount }}</div>
                </div>
              </div>
            </div>

            <!-- 搜索按钮 -->
            <div class="setting-row vertical">
              <div class="setting-control">
                <t-button
                  theme="primary"
                  block
                  :loading="searching"
                  @click="handleSearch"
                  class="search-button"
                >
                  {{ searching ? $t('knowledgeEditor.faq.searching') : $t('knowledgeEditor.faq.searchButton') }}
                </t-button>
              </div>
            </div>
          </div>
        </t-form>

        <!-- Search Results -->
        <div v-if="searchResults.length > 0 || hasSearched" class="search-results">
          <div class="results-header">
            <span>{{ $t('knowledgeEditor.faq.searchResults') }} ({{ searchResults.length }})</span>
          </div>
          <div v-if="searchResults.length === 0" class="no-results">
            {{ $t('knowledgeEditor.faq.noResults') }}
          </div>
          <div v-else class="results-list">
            <div
              v-for="(result, index) in searchResults"
              :key="result.id"
              class="result-card"
              :class="{ 'expanded': result.expanded }"
            >
              <div class="result-header" @click="toggleResult(result)">
                <div class="result-question-wrapper">
                  <div class="result-question">
                    <span class="result-index">{{ index + 1 }}.</span>
                    {{ result.standard_question }}
                  </div>
                  <div class="result-meta">
                    <t-tag size="small" variant="light-outline" class="score-tag">
                      {{ $t('knowledgeEditor.faq.score') }}: {{ (result.score || 0).toFixed(3) }}
                    </t-tag>
                  </div>
                  <t-icon 
                    :name="result.expanded ? 'chevron-up' : 'chevron-down'" 
                    class="expand-icon"
                  />
                </div>
              </div>
              <Transition name="slide-down">
                <div v-if="result.expanded" class="result-body">
                  <div v-if="result.answers?.length" class="result-section">
                    <div class="section-label">{{ $t('knowledgeEditor.faq.answers') }}</div>
                    <div class="result-tags">
                      <t-tooltip
                        v-for="answer in result.answers"
                        :key="answer"
                        :content="answer"
                        placement="top"
                      >
                        <t-tag size="small" theme="success" variant="light" class="answer-tag">
                          {{ answer }}
                        </t-tag>
                      </t-tooltip>
                    </div>
                  </div>
                  <div v-if="result.similar_questions?.length" class="result-section">
                    <div class="section-label">{{ $t('knowledgeEditor.faq.similarQuestions') }}</div>
                    <div class="result-tags">
                      <t-tooltip
                        v-for="question in result.similar_questions"
                        :key="question"
                        :content="question"
                        placement="top"
                      >
                        <t-tag size="small" variant="light-outline" class="question-tag">
                          {{ question }}
                        </t-tag>
                      </t-tooltip>
                    </div>
                  </div>
                </div>
              </Transition>
            </div>
          </div>
        </div>
      </div>
    </t-drawer>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, watch, onMounted, computed, nextTick, onUnmounted, h } from 'vue'
import type { ComponentPublicInstance } from 'vue'
import { MessagePlugin, DialogPlugin, Icon as TIcon } from 'tdesign-vue-next'
import type { FormRules, FormInstanceFunctions } from 'tdesign-vue-next'
import { useI18n } from 'vue-i18n'
import { useRouter } from 'vue-router'
import {
  listFAQEntries,
  upsertFAQEntries,
  createFAQEntry,
  updateFAQEntry,
  updateFAQEntryStatusBatch,
  deleteFAQEntries,
  searchFAQEntries,
  listKnowledgeTags,
  updateFAQEntryTagBatch,
  createKnowledgeBaseTag,
  updateKnowledgeBaseTag,
  deleteKnowledgeBaseTag,
  getKnowledgeBaseById,
  listKnowledgeBases,
  getKnowledgeDetails,
} from '@/api/knowledge-base'
import * as XLSX from 'xlsx'
import Papa from 'papaparse'
import FAQTagTooltip from '@/components/FAQTagTooltip.vue'
import { useUIStore } from '@/stores/ui'

interface FAQEntry {
  id: string
  chunk_id: string
  knowledge_id: string
  knowledge_base_id: string
  tag_id?: string
  is_enabled: boolean
  standard_question: string
  similar_questions: string[]
  negative_questions: string[]
  answers: string[]
  updated_at: string
  showMore?: boolean
  score?: number
  match_type?: string
  expanded?: boolean
  similarCollapsed?: boolean
  negativeCollapsed?: boolean
  answersCollapsed?: boolean
}

interface FAQEntryPayload {
  standard_question: string
  similar_questions: string[]
  negative_questions: string[]
  answers: string[]
  tag_id?: string
  is_enabled?: boolean
}

const props = defineProps<{
  kbId: string
}>()

const { t } = useI18n()
const router = useRouter()
const uiStore = useUIStore()

const loading = ref(false)
const loadingMore = ref(false)
const entries = ref<FAQEntry[]>([])
const entryStatusLoading = reactive<Record<string, boolean>>({})
const selectedRowKeys = ref<string[]>([])
const scrollContainer = ref<HTMLElement | null>(null)
const cardListRef = ref<HTMLElement | null>(null)
const hasMore = ref(true)
const pageSize = 20
let currentPage = 1
const entrySearchKeyword = ref('')
let entrySearchDebounce: ReturnType<typeof setTimeout> | null = null
type TagInputInstance = ComponentPublicInstance<{ focus: () => void; select: () => void }>

const tagList = ref<any[]>([])
const tagLoading = ref(false)
const tagListRef = ref<HTMLElement | null>(null)
const selectedTagId = ref<string>('')
const overallFAQTotal = ref(0)
const tagSearchQuery = ref('')
const TAG_PAGE_SIZE = 20
const tagPage = ref(1)
const tagHasMore = ref(false)
const tagLoadingMore = ref(false)
const tagTotal = ref(0)
let tagSearchDebounce: ReturnType<typeof setTimeout> | null = null
const editingTagInputRefs = new Map<string, TagInputInstance | null>()
const setEditingTagInputRef = (el: TagInputInstance | null, tagId: string) => {
  if (el) {
    editingTagInputRefs.set(tagId, el)
  } else {
    editingTagInputRefs.delete(tagId)
  }
}
const setEditingTagInputRefByTag = (tagId: string) => (el: TagInputInstance | null) => {
  setEditingTagInputRef(el, tagId)
}
const newTagInputRef = ref<TagInputInstance | null>(null)
const creatingTag = ref(false)
const creatingTagLoading = ref(false)
const newTagName = ref('')
const editingTagId = ref<string | null>(null)
const editingTagName = ref('')
const editingTagSubmitting = ref(false)
const tagDropdownOptions = computed(() => [
  { content: t('knowledgeBase.untagged') || '未分类', value: '' },
  ...tagList.value.map((tag: any) => ({ content: tag.name, value: tag.id })),
])
const tagMap = computed<Record<string, any>>(() => {
  const map: Record<string, any> = {}
  tagList.value.forEach((tag) => {
    map[tag.id] = tag
  })
  return map
})
const tagSelectOptions = computed(() => [
  { label: t('knowledgeBase.untagged') || '未分类', value: '' },
  ...tagList.value.map((tag: any) => ({ label: tag.name, value: tag.id })),
])
const sidebarCategoryCount = computed(() => tagList.value.length + 1)
const assignedFAQCount = computed(() =>
  tagList.value.reduce((sum, tag) => sum + (tag.chunk_count || 0), 0),
)
const untaggedFAQCount = computed(() =>
  Math.max(overallFAQTotal.value - assignedFAQCount.value, 0),
)
const filteredTags = computed(() => {
  const query = tagSearchQuery.value.trim().toLowerCase()
  if (!query) {
    return tagList.value
  }
  return tagList.value.filter((tag) => (tag.name || '').toLowerCase().includes(query))
})

const kbInfo = ref<any>(null)
const knowledgeList = ref<Array<{ id: string; name: string; type?: string }>>([])
const knowledgeDropdownOptions = computed(() =>
  knowledgeList.value
    .map((item) => ({
      content: item.name,
      value: item.id,
      prefixIcon: () => h(TIcon, { name: item.type === 'document' ? 'folder' : 'chat-bubble-help', size: '16px' }),
    })),
)

const loadKnowledgeInfo = async (kbId: string) => {
  if (!kbId) {
    kbInfo.value = null
    return
  }
  try {
    const res: any = await getKnowledgeBaseById(kbId)
    kbInfo.value = res?.data || null
    return kbInfo.value
  } catch (error) {
    console.error('Failed to load knowledge base info:', error)
    kbInfo.value = null
    return null
  }
}

const loadKnowledgeList = async () => {
  try {
    const res: any = await listKnowledgeBases()
    knowledgeList.value = (res?.data || []).map((item: any) => ({
      id: String(item.id),
      name: item.name,
      type: item.type,
    }))
  } catch (error) {
    console.error('Failed to load knowledge bases:', error)
  }
}

const editorVisible = ref(false)
const editorMode = ref<'create' | 'edit'>('create')
const currentEntryId = ref<string | null>(null)
const editorForm = reactive<FAQEntryPayload>({
  standard_question: '',
  similar_questions: [],
  negative_questions: [],
  answers: [],
  tag_id: '',
})
const editorFormRef = ref<FormInstanceFunctions>()
const savingEntry = ref(false)

// 输入框状态
const answerInput = ref('')
const similarInput = ref('')
const negativeInput = ref('')

const importVisible = ref(false)
const fileInputRef = ref<HTMLInputElement | null>(null)
const importState = reactive({
  mode: 'append' as 'append' | 'replace',
  file: null as File | null,
  preview: [] as FAQEntryPayload[],
  importing: false,
  taskId: null as string | null,
  taskStatus: null as {
    status: string
    progress: number
    total: number
    processed: number
    error?: string
  } | null,
  pollingInterval: null as ReturnType<typeof setInterval> | null,
})

// Search test state
const searchDrawerVisible = ref(false)
const searching = ref(false)
const hasSearched = ref(false)
const searchResults = ref<FAQEntry[]>([])
const searchForm = reactive({
  query: '',
  vectorThreshold: 0.7,
  matchCount: 10,
})

// Toolbar actions dropdown
const toolbarActionOptions = computed(() => {
  const options = [
    { 
      content: t('knowledgeEditor.faqImport.importButton'), 
      value: 'import', 
      icon: 'upload',
      disabled: importState.taskStatus?.status === 'running' // 导入过程中禁用导入按钮
    },
    { content: t('knowledgeEditor.faq.searchTest'), value: 'search', icon: 'search' },
  ]
  
  // 如果有选中的条目，添加批量操作选项
  if (selectedRowKeys.value.length > 0) {
    options.push(
      {
        content: `${t('knowledgeEditor.faq.batchUpdateTag')} (${selectedRowKeys.value.length})`,
        value: 'batchTag',
        icon: 'folder',
      },
      {
        content: `${t('knowledgeEditor.faq.batchEnable')} (${selectedRowKeys.value.length})`,
        value: 'batchEnable',
        icon: 'check-circle',
      },
      {
        content: `${t('knowledgeEditor.faq.batchDisable')} (${selectedRowKeys.value.length})`,
        value: 'batchDisable',
        icon: 'close-circle',
      },
      {
        content: `${t('knowledgeEditor.faqImport.deleteSelected')} (${selectedRowKeys.value.length})`,
        value: 'delete',
        icon: 'delete',
      }
    )
  }
  
  return options
})

const handleToolbarAction = (data: { value: string }) => {
  switch (data.value) {
    case 'import':
      openImportDialog()
      break
    case 'search':
      searchDrawerVisible.value = true
      break
    case 'batchTag':
      openBatchTagDialog()
      break
    case 'batchEnable':
      handleBatchStatusChange(true)
      break
    case 'batchDisable':
      handleBatchStatusChange(false)
      break
    case 'delete':
      handleBatchDelete()
      break
  }
}

// 标签列表滚动加载更多
const handleTagListScroll = () => {
  const container = tagListRef.value
  if (!container) return
  if (tagLoadingMore.value || !tagHasMore.value) return
  
  const { scrollTop, scrollHeight, clientHeight } = container
  // 距离底部 50px 时触发加载
  if (scrollTop + clientHeight >= scrollHeight - 50) {
    loadTags()
  }
}

const loadTags = async (reset = false) => {
  if (!props.kbId) {
    tagList.value = []
    tagTotal.value = 0
    tagHasMore.value = false
    tagPage.value = 1
    return
  }

  if (reset) {
    tagPage.value = 1
    tagList.value = []
    tagTotal.value = 0
    tagHasMore.value = false
  }

  const currentPage = tagPage.value || 1
  tagLoading.value = currentPage === 1
  tagLoadingMore.value = currentPage > 1

  try {
    const res: any = await listKnowledgeTags(props.kbId, {
      page: currentPage,
      page_size: TAG_PAGE_SIZE,
      keyword: tagSearchQuery.value || undefined,
    })
    const pageData = (res?.data || {}) as {
      data?: any[]
      total?: number
    }
    const pageTags = (pageData.data || []).map((tag: any) => ({
      ...tag,
      id: String(tag.id),
    }))

    if (currentPage === 1) {
      tagList.value = pageTags
    } else {
      tagList.value = [...tagList.value, ...pageTags]
    }

    tagTotal.value = pageData.total || tagList.value.length
    tagHasMore.value = tagList.value.length < tagTotal.value
    if (tagHasMore.value) {
      tagPage.value = currentPage + 1
    }
  } catch (error: any) {
    MessagePlugin.error(error?.message || t('common.operationFailed'))
  } finally {
    tagLoading.value = false
    tagLoadingMore.value = false
  }
}

const getTagName = (tagId?: string) => {
  if (!tagId) return t('knowledgeBase.untagged') || '未分类'
  return tagMap.value[tagId]?.name || (t('knowledgeBase.untagged') || '未分类')
}

const handleTagFilterChange = (value: string) => {
  selectedTagId.value = value
}

const handleTagRowClick = (tagId: string) => {
  const normalizedId = String(tagId)
  if (editingTagId.value && editingTagId.value !== normalizedId) {
    cancelEditTag()
  }
  if (creatingTag.value) {
    cancelCreateTag()
  }
  if (selectedTagId.value === normalizedId) {
    return
  }
  handleTagFilterChange(normalizedId)
}

const handleUntaggedClick = () => {
  if (creatingTag.value) {
    cancelCreateTag()
  }
  if (editingTagId.value) {
    cancelEditTag()
  }
  if (selectedTagId.value === '') return
  handleTagFilterChange('')
}

const startCreateTag = () => {
  if (!props.kbId) {
    MessagePlugin.warning(t('knowledgeEditor.messages.missingId'))
    return
  }
  if (creatingTag.value) {
    return
  }
  cancelEditTag()
  creatingTag.value = true
  nextTick(() => {
    newTagInputRef.value?.focus?.()
    newTagInputRef.value?.select?.()
  })
}

const cancelCreateTag = () => {
  creatingTag.value = false
  newTagName.value = ''
}

const submitCreateTag = async () => {
  if (!props.kbId) {
    MessagePlugin.warning(t('knowledgeEditor.messages.missingId'))
    return
  }
  const name = newTagName.value.trim()
  if (!name) {
    MessagePlugin.warning(t('knowledgeBase.tagNameRequired'))
    return
  }
  creatingTagLoading.value = true
  try {
    await createKnowledgeBaseTag(props.kbId, { name })
    MessagePlugin.success(t('knowledgeBase.tagCreateSuccess'))
    cancelCreateTag()
    await loadTags()
  } catch (error: any) {
    MessagePlugin.error(error?.message || t('common.operationFailed'))
  } finally {
    creatingTagLoading.value = false
  }
}

const startEditTag = (tag: any) => {
  cancelCreateTag()
  editingTagId.value = tag.id
  editingTagName.value = tag.name
  nextTick(() => {
    const inputRef = editingTagInputRefs.get(tag.id)
    inputRef?.focus?.()
    inputRef?.select?.()
  })
}

const cancelEditTag = () => {
  editingTagId.value = null
  editingTagName.value = ''
}

const submitEditTag = async () => {
  if (!props.kbId || !editingTagId.value) {
    return
  }
  const name = editingTagName.value.trim()
  if (!name) {
    MessagePlugin.warning(t('knowledgeBase.tagNameRequired'))
    return
  }
  if (name === tagMap.value[editingTagId.value]?.name) {
    cancelEditTag()
    return
  }
  editingTagSubmitting.value = true
  try {
    await updateKnowledgeBaseTag(props.kbId, editingTagId.value, { name })
    MessagePlugin.success(t('knowledgeBase.tagEditSuccess'))
    cancelEditTag()
    await loadTags()
  } catch (error: any) {
    MessagePlugin.error(error?.message || t('common.operationFailed'))
  } finally {
    editingTagSubmitting.value = false
  }
}

const confirmDeleteTag = (tag: any) => {
  if (!props.kbId) {
    MessagePlugin.warning(t('knowledgeEditor.messages.missingId'))
    return
  }
  if (creatingTag.value) {
    cancelCreateTag()
  }
  if (editingTagId.value) {
    cancelEditTag()
  }
  const confirmDialog = DialogPlugin.confirm({
    header: t('knowledgeBase.tagDeleteTitle'),
    body: t('knowledgeBase.tagDeleteDesc', { name: tag.name }),
    confirmBtn: { content: t('common.delete'), theme: 'danger' },
    cancelBtn: t('common.cancel'),
    onConfirm: async () => {
      try {
        await deleteKnowledgeBaseTag(props.kbId, tag.id)
        MessagePlugin.success(t('knowledgeBase.tagDeleteSuccess'))
        if (selectedTagId.value === tag.id) {
          handleTagFilterChange('')
        }
        await loadTags()
        confirmDialog.hide()
      } catch (error: any) {
        MessagePlugin.error(error?.message || t('common.operationFailed'))
      }
    },
  })
}

const handleEntryTagChange = async (entryId: string, value?: string) => {
  if (!props.kbId) return
  const targetEntry = entries.value.find((item) => item.id === entryId)
  const previousTagId = targetEntry ? targetEntry.tag_id : ''
  const normalizedValue = value ?? ''
  if (normalizedValue === previousTagId) {
    return
  }
  try {
    await updateFAQEntryTagBatch(props.kbId, { updates: { [entryId]: normalizedValue || null } })
    MessagePlugin.success(t('knowledgeEditor.messages.updateSuccess'))
    await loadEntries()
    await loadTags()
  } catch (error: any) {
    if (targetEntry) {
      targetEntry.tag_id = previousTagId
    }
    MessagePlugin.error(error?.message || t('common.operationFailed'))
  }
}

const handleNavigateToKbList = () => {
  router.push('/platform/knowledge-bases')
}

const handleNavigateToCurrentKB = () => {
  if (!props.kbId) return
  router.push(`/platform/knowledge-bases/${props.kbId}`)
}

const handleOpenKBSettings = () => {
  if (!props.kbId) {
    MessagePlugin.warning(t('knowledgeEditor.messages.missingId'))
    return
  }
  uiStore.openKBSettings(props.kbId)
}

const handleKnowledgeDropdownSelect = (data: { value: string }) => {
  if (!data?.value || data.value === props.kbId) return
  router.push(`/platform/knowledge-bases/${data.value}`)
}

const handleFaqMenuAction = (event: Event) => {
  const detail = (event as CustomEvent<{ action: string; kbId: string }>).detail
  if (!detail || detail.kbId !== props.kbId) return
  if (detail.action === 'create') {
    openEditor()
  } else if (detail.action === 'import') {
    openImportDialog()
  } else if (detail.action === 'search') {
    searchDrawerVisible.value = true
  } else if (detail.action === 'batch') {
    // 批量操作通过左侧菜单的下拉菜单处理
    if (selectedRowKeys.value.length === 0) {
      MessagePlugin.warning(t('knowledgeEditor.faq.selectEntriesFirst') || '请先选中要操作的FAQ条目')
    }
  } else if (detail.action === 'batchTag') {
    if (selectedRowKeys.value.length > 0) {
      openBatchTagDialog()
    }
  } else if (detail.action === 'batchEnable') {
    if (selectedRowKeys.value.length > 0) {
      handleBatchStatusChange(true)
    }
  } else if (detail.action === 'batchDisable') {
    if (selectedRowKeys.value.length > 0) {
      handleBatchStatusChange(false)
    }
  } else if (detail.action === 'batchDelete') {
    if (selectedRowKeys.value.length > 0) {
      handleBatchDelete()
    }
  }
}

const handleEntryStatusChange = async (entry: FAQEntry, value: boolean) => {
  if (!props.kbId) {
    return
  }
  const entryIndex = entries.value.findIndex(e => e.id === entry.id)
  if (entryIndex === -1) {
    return
  }
  // 从数组中获取实际的对象引用，确保使用最新的数据
  const actualEntry = entries.value[entryIndex]
  const previous = actualEntry.is_enabled
  if (previous === value) {
    return
  }
  // 直接更新属性，Vue 3 的响应式系统应该能够检测到
  actualEntry.is_enabled = value
  entryStatusLoading[entry.id] = true
  try {
    await updateFAQEntryStatusBatch(props.kbId, { updates: { [entry.id]: value } })
    MessagePlugin.success(t(value ? 'knowledgeEditor.faq.statusEnableSuccess' : 'knowledgeEditor.faq.statusDisableSuccess'))
  } catch (error: any) {
    // 失败时回滚
    actualEntry.is_enabled = previous
    MessagePlugin.error(error?.message || t('knowledgeEditor.faq.statusUpdateFailed'))
  } finally {
    entryStatusLoading[entry.id] = false
  }
}

const editorRules: FormRules<FAQEntryPayload> = {
  standard_question: [
    { required: true, message: t('knowledgeEditor.messages.nameRequired') },
  ],
  answers: [
    {
      validator: (val: string[]) => Array.isArray(val) && val.length > 0,
      message: t('knowledgeEditor.faq.answerRequired'),
    },
  ],
}

const loadEntries = async (append = false) => {
  if (!props.kbId) return
  if (append) {
    loadingMore.value = true
  } else {
    loading.value = true
    currentPage = 1
    entries.value = []
    selectedRowKeys.value = []
    Object.keys(entryStatusLoading).forEach((key) => {
      delete entryStatusLoading[key]
    })
  }

  try {
    const res = await listFAQEntries(props.kbId, {
      page: currentPage,
      page_size: pageSize,
      tag_id: selectedTagId.value || undefined,
      keyword: entrySearchKeyword.value ? entrySearchKeyword.value.trim() : undefined,
    })
    const pageData = (res.data || {}) as {
      data: FAQEntry[]
      total: number
    }
    const newEntries = (pageData.data || []).map(entry => ({
      ...entry,
      showMore: false,
      similarCollapsed: true,  // 相似问默认折叠
      negativeCollapsed: true,  // 反例默认折叠
      answersCollapsed: true,   // 答案默认折叠
      tag_id: entry.tag_id ? String(entry.tag_id) : '',
      is_enabled: entry.is_enabled !== false,
    }))
    
    if (append) {
      entries.value = [...entries.value, ...newEntries]
    } else {
      entries.value = newEntries
    }
    if (selectedTagId.value === '') {
      overallFAQTotal.value = pageData.total || 0
    }
    // 判断是否还有更多数据
    hasMore.value = entries.value.length < (pageData.total || 0)
    currentPage++
    
    // 等待 DOM 更新后重新布局
    await nextTick()
    arrangeCards()
  } catch (error: any) {
    MessagePlugin.error(error?.message || t('common.operationFailed'))
  } finally {
    loading.value = false
    loadingMore.value = false
    
    // 检查是否需要继续加载以填满可视区域
    // 延迟执行以确保 arrangeCards 的 requestAnimationFrame 完成
    setTimeout(() => {
      checkAndLoadMore()
    }, 350)
  }
}

const handleScroll = () => {
  if (!scrollContainer.value || loadingMore.value || !hasMore.value) return

  const container = scrollContainer.value
  const scrollTop = container.scrollTop
  const scrollHeight = container.scrollHeight
  const clientHeight = container.clientHeight

  // 当滚动到距离底部 200px 时加载更多
  if (scrollTop + clientHeight >= scrollHeight - 200) {
    loadEntries(true)
  }
}

// 检查内容是否填满可视区域，如果没有且还有更多数据，继续加载
const checkAndLoadMore = () => {
  if (!scrollContainer.value) return
  if (loadingMore.value || loading.value) return
  if (!hasMore.value) return
  
  const container = scrollContainer.value
  const scrollHeight = container.scrollHeight
  const clientHeight = container.clientHeight
  
  // 如果内容高度小于容器高度 + 50px 的缓冲，说明可能没有滚动条或接近底部，需要继续加载
  if (scrollHeight <= clientHeight + 50) {
    loadEntries(true)
  }
}

const handleCardSelect = (entryId: string, checked: boolean) => {
  if (checked) {
    if (!selectedRowKeys.value.includes(entryId)) {
      selectedRowKeys.value.push(entryId)
    }
  } else {
    const index = selectedRowKeys.value.indexOf(entryId)
    if (index > -1) {
      selectedRowKeys.value.splice(index, 1)
    }
  }
}

const resetEditorForm = () => {
  editorForm.standard_question = ''
  editorForm.similar_questions = []
  editorForm.negative_questions = []
  editorForm.answers = []
  editorForm.tag_id = ''
  answerInput.value = ''
  similarInput.value = ''
  negativeInput.value = ''
}

const openEditor = (entry?: FAQEntry) => {
  if (entry) {
    editorMode.value = 'edit'
    currentEntryId.value = entry.id
    editorForm.standard_question = entry.standard_question
    editorForm.similar_questions = [...(entry.similar_questions || [])]
    editorForm.negative_questions = [...(entry.negative_questions || [])]
    editorForm.answers = [...(entry.answers || [])]
    editorForm.tag_id = entry.tag_id || ''
  } else {
    editorMode.value = 'create'
    currentEntryId.value = null
    resetEditorForm()
  }
  answerInput.value = ''
  similarInput.value = ''
  negativeInput.value = ''
  editorVisible.value = true
}

const handleEditorClose = () => {
  // 关闭时重置表单
  resetEditorForm()
  answerInput.value = ''
  similarInput.value = ''
  negativeInput.value = ''
  editorFormRef.value?.clearValidate?.()
}

// 添加答案
const addAnswer = () => {
  const trimmed = answerInput.value.trim()
  if (trimmed && editorForm.answers.length < 5 && !editorForm.answers.includes(trimmed)) {
    editorForm.answers.push(trimmed)
    answerInput.value = ''
  }
}

// 删除答案
const removeAnswer = (index: number) => {
  editorForm.answers.splice(index, 1)
}

// 添加相似问
const addSimilar = () => {
  const trimmed = similarInput.value.trim()
  if (trimmed && editorForm.similar_questions.length < 10 && !editorForm.similar_questions.includes(trimmed)) {
    editorForm.similar_questions.push(trimmed)
    similarInput.value = ''
  }
}

// 删除相似问
const removeSimilar = (index: number) => {
  editorForm.similar_questions.splice(index, 1)
}

// 添加反例
const addNegative = () => {
  const trimmed = negativeInput.value.trim()
  if (trimmed && editorForm.negative_questions.length < 10 && !editorForm.negative_questions.includes(trimmed)) {
    editorForm.negative_questions.push(trimmed)
    negativeInput.value = ''
  }
}

// 删除反例
const removeNegative = (index: number) => {
  editorForm.negative_questions.splice(index, 1)
}

const handleSubmitEntry = async () => {
  if (!editorFormRef.value) return
  const result = await editorFormRef.value.validate?.()
  if (result !== true) return

  savingEntry.value = true
  try {
    const payload: FAQEntryPayload = {
      standard_question: editorForm.standard_question,
      similar_questions: [...editorForm.similar_questions],
      negative_questions: [...editorForm.negative_questions],
      answers: [...editorForm.answers],
      tag_id: editorForm.tag_id || '',
    }
    if (editorMode.value === 'create') {
      await createFAQEntry(props.kbId, payload)
      MessagePlugin.success(t('knowledgeEditor.messages.createSuccess'))
    } else if (currentEntryId.value) {
      await updateFAQEntry(props.kbId, currentEntryId.value, payload)
      MessagePlugin.success(t('knowledgeEditor.messages.updateSuccess'))
    }
    editorVisible.value = false
    await loadEntries()
  } catch (error: any) {
    MessagePlugin.error(error?.message || t('common.operationFailed'))
  } finally {
    savingEntry.value = false
  }
}

const handleBatchDelete = async () => {
  if (!selectedRowKeys.value.length) return
  try {
    await deleteFAQEntries(props.kbId, selectedRowKeys.value)
    MessagePlugin.success(t('knowledgeEditor.faqImport.deleteSuccess'))
    selectedRowKeys.value = []
    await loadEntries()
  } catch (error: any) {
    MessagePlugin.error(error?.message || t('common.operationFailed'))
  }
}

// 批量状态更新对话框
const batchTagDialogVisible = ref(false)
const batchTagValue = ref<string>('')

const openBatchTagDialog = () => {
  if (!selectedRowKeys.value.length) return
  batchTagValue.value = ''
  batchTagDialogVisible.value = true
}

const handleBatchTag = async () => {
  if (!selectedRowKeys.value.length || !props.kbId) return
  try {
    const updates: Record<string, string | null> = {}
    selectedRowKeys.value.forEach(id => {
      updates[id] = batchTagValue.value || null
    })
    await updateFAQEntryTagBatch(props.kbId, { updates })
    MessagePlugin.success(t('knowledgeEditor.messages.updateSuccess'))
    batchTagDialogVisible.value = false
    selectedRowKeys.value = []
    await loadEntries()
    await loadTags()
  } catch (error: any) {
    MessagePlugin.error(error?.message || t('common.operationFailed'))
  }
}

const handleBatchStatusChange = async (isEnabled: boolean) => {
  if (!selectedRowKeys.value.length || !props.kbId) return
  try {
    const updates: Record<string, boolean> = {}
    selectedRowKeys.value.forEach(id => {
      updates[id] = isEnabled
    })
    await updateFAQEntryStatusBatch(props.kbId, { updates })
    MessagePlugin.success(t(isEnabled ? 'knowledgeEditor.faq.statusEnableSuccess' : 'knowledgeEditor.faq.statusDisableSuccess'))
    selectedRowKeys.value = []
    await loadEntries()
  } catch (error: any) {
    MessagePlugin.error(error?.message || t('common.operationFailed'))
  }
}

const handleMenuEdit = (entry: FAQEntry) => {
  entry.showMore = false
  openEditor(entry)
}

const handleMenuDelete = async (entry: FAQEntry) => {
  entry.showMore = false
  try {
    await deleteFAQEntries(props.kbId, [entry.id])
    MessagePlugin.success(t('knowledgeEditor.faqImport.deleteSuccess'))
    await loadEntries()
  } catch (error: any) {
    MessagePlugin.error(error?.message || t('common.operationFailed'))
  }
}

const openImportDialog = () => {
  // 如果正在导入，不允许打开导入对话框
  if (importState.taskStatus?.status === 'running') {
    MessagePlugin.warning('导入正在进行中，请等待完成后再试')
    return
  }
  stopPolling()
  importVisible.value = true
  importState.file = null
  importState.preview = []
  importState.mode = 'append'
  // 注意：不清除taskId和taskStatus，以便在关闭对话框后仍能看到进度
  importState.importing = false
}

const processFile = async (file: File) => {
  importState.file = file

  try {
    let parsed: FAQEntryPayload[] = []
    if (file.name.endsWith('.json')) {
      parsed = await parseJSONFile(file)
    } else if (file.name.endsWith('.csv')) {
      parsed = await parseCSVFile(file)
    } else if (file.name.endsWith('.xlsx') || file.name.endsWith('.xls')) {
      parsed = await parseExcelFile(file)
    } else {
      MessagePlugin.warning(t('knowledgeEditor.faqImport.unsupportedFormat'))
      importState.preview = []
      return
    }
    importState.preview = parsed
  } catch (error: any) {
    MessagePlugin.error(error?.message || t('knowledgeEditor.faqImport.parseFailed'))
    importState.preview = []
  }
}

const handleFileChange = async (event: Event) => {
  const target = event.target as HTMLInputElement
  const file = target.files?.[0]
  if (!file) return
  await processFile(file)
}

const handleFileDrop = async (event: DragEvent) => {
  const file = event.dataTransfer?.files[0]
  if (!file) return
  await processFile(file)
}

const parseJSONFile = async (file: File): Promise<FAQEntryPayload[]> => {
  const text = await file.text()
  const data = JSON.parse(text)
  if (!Array.isArray(data)) {
    throw new Error(t('knowledgeEditor.faqImport.invalidJSON'))
  }
  return data.map(normalizePayload)
}

const parseCSVFile = async (file: File): Promise<FAQEntryPayload[]> => {
  const text = await file.text()
  
  // 使用 papaparse 解析 CSV，自动处理引号、转义、分隔符等
  return new Promise((resolve, reject) => {
    Papa.parse(text, {
      header: true,
      skipEmptyLines: true,
      delimiter: '', // 自动检测分隔符（逗号或制表符）
      quoteChar: '"',
      escapeChar: '"',
      transformHeader: (header: string) => {
        // 移除字段名中的括号和说明，只保留核心字段名
        const cleaned = header.trim()
          .replace(/\([^)]*\)/g, '') // 移除括号及内容
          .trim()
        // 对于中文字段名，不转换为小写；对于英文字段名，转换为小写
        return /[\u4e00-\u9fa5]/.test(cleaned) ? cleaned : cleaned.toLowerCase()
      },
      complete: (results) => {
        try {
          const payloads: FAQEntryPayload[] = []
          results.data.forEach((row: any) => {
            const record: Record<string, string> = {}
            // 将行数据转换为记录对象
            Object.keys(row).forEach((key) => {
              record[key] = String(row[key] || '').trim()
            })
            
            const isDisabled = parseBooleanField(record['是否停用'], false)
            payloads.push(
              normalizePayload({
                standard_question: record['问题'] || record['standard_question'] || record['question'] || '',
                answers: splitByDelimiter(record['机器人回答'] || record['answers']),
                similar_questions: splitByDelimiter(record['相似问题'] || record['similar_questions']),
                negative_questions: splitByDelimiter(record['反例问题'] || record['negative_questions']),
                tag_id: record['分类'] || record['tag_id'] || '',
                is_enabled: isDisabled !== undefined ? !isDisabled : undefined, // 是否停用：FALSE表示启用，TRUE表示停用，所以取反
              }),
            )
          })
          resolve(payloads)
        } catch (error) {
          reject(error)
        }
      },
      error: (error: Error) => {
        reject(new Error(`CSV解析失败: ${error.message}`))
      },
    })
  })
}

const parseExcelFile = async (file: File): Promise<FAQEntryPayload[]> => {
  const data = await file.arrayBuffer()
  const workbook = XLSX.read(data, { type: 'array' })
  const sheetName = workbook.SheetNames[0]
  const worksheet = workbook.Sheets[sheetName]
  // 使用 raw: false 确保正确处理引号和转义
  const json = XLSX.utils.sheet_to_json<Record<string, string>>(worksheet, { 
    defval: '',
    raw: false // 确保字符串值被正确解析
  })
  return json.map((row) => {
    // 获取原始表头（去除括号说明）
    const normalizedRow: Record<string, string> = {}
    Object.keys(row).forEach((key) => {
      const normalizedKey = key.trim()
        .replace(/\([^)]*\)/g, '') // 移除括号及内容
        .trim()
      // 对于中文字段名，不转换为小写；对于英文字段名，转换为小写
      const finalKey = /[\u4e00-\u9fa5]/.test(normalizedKey) ? normalizedKey : normalizedKey.toLowerCase()
      // 确保值是字符串类型
      normalizedRow[finalKey] = String(row[key] || '').trim()
    })
    
    const isDisabled = parseBooleanField(normalizedRow['是否停用'], false)
    return normalizePayload({
      standard_question: normalizedRow['问题'] || normalizedRow['standard_question'] || normalizedRow['question'] || '',
      answers: splitByDelimiter(normalizedRow['机器人回答'] || normalizedRow['answers']),
      similar_questions: splitByDelimiter(normalizedRow['相似问题'] || normalizedRow['similar_questions']),
      negative_questions: splitByDelimiter(normalizedRow['反例问题'] || normalizedRow['negative_questions']),
      tag_id: normalizedRow['分类'] || normalizedRow['tag_id'] || '',
      is_enabled: isDisabled !== undefined ? !isDisabled : undefined, // 是否停用：FALSE表示启用，TRUE表示停用，所以取反
    })
  })
}

const splitByDelimiter = (value?: string) => {
  if (!value) return []
  // 只使用 ## 作为分隔符，避免错误分割包含逗号、分号等内容
  const trimmedValue = value.trim()
  if (!trimmedValue) return []
  
  // 如果包含 ## 分隔符，按 ## 分割
  if (trimmedValue.includes('##')) {
    return trimmedValue
      .split('##')
      .map(item => item.trim())
      .filter(Boolean)
  }
  
  // 如果没有 ## 分隔符，整个值作为一个答案
  return [trimmedValue]
}

// 解析布尔字段（支持多种格式：TRUE/FALSE, true/false, 是/否, 1/0等）
const parseBooleanField = (value?: string, defaultValue: boolean = true): boolean | undefined => {
  if (!value) return undefined
  const normalized = value.trim().toUpperCase()
  if (normalized === 'TRUE' || normalized === '1' || normalized === '是' || normalized === 'YES') {
    return true
  }
  if (normalized === 'FALSE' || normalized === '0' || normalized === '否' || normalized === 'NO') {
    return false
  }
  return defaultValue
}

const normalizePayload = (payload: Partial<FAQEntryPayload>): FAQEntryPayload => ({
  standard_question: payload.standard_question || '',
  answers: payload.answers?.filter(Boolean) || [],
  similar_questions: payload.similar_questions?.filter(Boolean) || [],
  negative_questions: payload.negative_questions?.filter(Boolean) || [],
  tag_id: payload.tag_id || '',
  is_enabled: payload.is_enabled !== undefined ? payload.is_enabled : undefined,
})

const stopPolling = () => {
  if (importState.pollingInterval) {
    clearInterval(importState.pollingInterval)
    importState.pollingInterval = null
  }
}

const startPolling = (taskId: string) => {
  stopPolling()
  // 保存taskId到localStorage，以便刷新后恢复
  saveTaskIdToStorage(taskId)
  
  // 记录上次已处理数量，用于判断是否需要刷新列表
  let lastProcessed = 0
  
  importState.pollingInterval = setInterval(async () => {
    try {
      const res: any = await getKnowledgeDetails(taskId)
      const knowledge = res?.data
      if (knowledge) {
        // 从Knowledge对象中提取导入任务状态
        // ParseStatus: "pending" -> "pending", "processing" -> "running", "completed" -> "success", "failed" -> "failed"
        let status = knowledge.parse_status
        if (status === 'processing') {
          status = 'running'
        } else if (status === 'completed') {
          status = 'success'
        }
        
        // 从Metadata中提取导入进度信息
        const metadata = knowledge.metadata || {}
        const progress = metadata.import_progress || 0
        const total = metadata.import_total || 0
        const processed = metadata.import_processed || 0
        const error = knowledge.error_message || ''
        
        importState.taskStatus = {
          status: status,
          progress: progress,
          total: total,
          processed: processed,
          error: error,
        }

        // 进度更新时刷新FAQ列表（每增加一些条目就刷新一次）
        if (processed > lastProcessed) {
          lastProcessed = processed
          await loadEntries()
        }

        // 任务完成或失败，停止轮询（但不自动关闭进度条，让用户手动关闭）
        if (status === 'success' || status === 'failed') {
          stopPolling()
          if (status === 'success') {
            MessagePlugin.success(t('knowledgeEditor.faqImport.importSuccess'))
            await loadEntries()
            // 任务完成后，3秒后自动关闭进度条
            setTimeout(() => {
              if (importState.taskStatus?.status === 'success') {
                handleCloseProgress()
              }
            }, 3000)
          } else {
            MessagePlugin.error(error || t('common.operationFailed'))
            // 失败时不自动关闭，让用户看到错误信息
          }
        }
      }
    } catch (error: any) {
      console.error('Failed to poll task status:', error)
      // 如果任务不存在或已过期，清除存储
      if (error?.response?.status === 404 || error?.message?.includes('not found')) {
        clearTaskIdFromStorage()
        stopPolling()
        importState.taskId = null
        importState.taskStatus = null
      }
    }
  }, 3000) // 每3秒轮询一次
}

const handleCancelImport = () => {
  stopPolling()
  importState.importing = false
  importState.taskId = null
  importState.taskStatus = null
  importVisible.value = false
  // 注意：不清除localStorage，因为任务可能还在进行中
}

const handleCloseProgress = () => {
  stopPolling()
  importState.taskId = null
  importState.taskStatus = null
  clearTaskIdFromStorage()
}

// localStorage相关函数
const getStorageKey = () => {
  return `faq_import_task_${props.kbId}`
}

const saveTaskIdToStorage = (taskId: string) => {
  if (!props.kbId) return
  try {
    localStorage.setItem(getStorageKey(), taskId)
  } catch (error) {
    console.error('Failed to save taskId to localStorage:', error)
  }
}

const getTaskIdFromStorage = (): string | null => {
  if (!props.kbId) return null
  try {
    return localStorage.getItem(getStorageKey())
  } catch (error) {
    console.error('Failed to get taskId from localStorage:', error)
    return null
  }
}

const clearTaskIdFromStorage = () => {
  if (!props.kbId) return
  try {
    localStorage.removeItem(getStorageKey())
  } catch (error) {
    console.error('Failed to clear taskId from localStorage:', error)
  }
}

// 恢复导入任务状态（用于刷新后恢复）
const restoreImportTask = async () => {
  if (!props.kbId) return
  
  const savedTaskId = getTaskIdFromStorage()
  if (!savedTaskId) return

  try {
    // 查询Knowledge状态
    const res: any = await getKnowledgeDetails(savedTaskId)
    const knowledge = res?.data
    
    if (knowledge) {
      // 从Knowledge对象中提取导入任务状态
      let status = knowledge.parse_status
      if (status === 'processing') {
        status = 'running'
      } else if (status === 'completed') {
        status = 'success'
      }
      
      // 从Metadata中提取导入进度信息
      const metadata = knowledge.metadata || {}
      const progress = metadata.import_progress || 0
      const total = metadata.import_total || 0
      const processed = metadata.import_processed || 0
      const error = knowledge.error_message || ''
      
      importState.taskId = savedTaskId
      importState.taskStatus = {
        status: status,
        progress: progress,
        total: total,
        processed: processed,
        error: error,
      }
      
      // 如果任务还在进行中，恢复轮询
      if (status === 'pending' || status === 'running') {
        startPolling(savedTaskId)
      } else {
        // 任务已完成或失败，清除存储
        clearTaskIdFromStorage()
      }
    } else {
      // 任务不存在，清除存储
      clearTaskIdFromStorage()
    }
  } catch (error: any) {
    console.error('Failed to restore import task:', error)
    // 如果任务不存在或已过期，清除存储
    if (error?.response?.status === 404 || error?.message?.includes('not found')) {
      clearTaskIdFromStorage()
    }
  }
}

const handleImport = async () => {
  if (!importState.file || !importState.preview.length) {
    MessagePlugin.warning(t('knowledgeEditor.faqImport.selectFile'))
    return
  }

  // 如果任务已完成或失败，关闭对话框
  if (importState.taskStatus?.status === 'success' || importState.taskStatus?.status === 'failed') {
    if (importState.taskStatus.status === 'success') {
      handleCancelImport()
    } else {
      // 失败时重试
      importState.taskId = null
      importState.taskStatus = null
      importState.importing = false
    }
    return
  }

  importState.importing = true
  try {
    const res: any = await upsertFAQEntries(props.kbId, {
      entries: importState.preview,
      mode: importState.mode,
    })
    
    const taskId = res?.data?.task_id
    if (taskId) {
      importState.taskId = taskId
      importState.taskStatus = {
        status: 'pending',
        progress: 0,
        total: importState.preview.length,
        processed: 0,
      }
      // 开始轮询任务状态
      startPolling(taskId)
      // 立即关闭导入对话框，进度将在列表页面顶部显示
      importVisible.value = false
      // 重置导入对话框状态（但保留taskId和taskStatus用于进度显示）
      importState.file = null
      importState.preview = []
      importState.importing = false
    } else {
      // 如果没有返回任务ID，可能是旧版本API，使用同步方式
      MessagePlugin.success(t('knowledgeEditor.faqImport.importSuccess'))
      importVisible.value = false
      await loadEntries()
      importState.importing = false
    }
  } catch (error: any) {
    MessagePlugin.error(error?.message || t('common.operationFailed'))
    importState.importing = false
    stopPolling()
  }
}

// 监听选中数量变化，通知左侧菜单
watch(selectedRowKeys, (newKeys, oldKeys) => {
  const count = newKeys.length
  // 获取选中条目的状态信息
  const selectedEntries = entries.value.filter(entry => newKeys.includes(entry.id))
  const enabledCount = selectedEntries.filter(entry => entry.is_enabled !== false).length
  const disabledCount = count - enabledCount
  
  const event = new CustomEvent('faqSelectionChanged', {
    detail: { 
      count,
      enabledCount,
      disabledCount
    }
  })
  window.dispatchEvent(event)
}, { immediate: true, deep: true })

// 组件卸载时清理轮询
onUnmounted(() => {
  stopPolling()
})

// 下载示例文件选项
const downloadExampleOptions = computed(() => [
  { content: t('knowledgeEditor.faqImport.downloadExampleJSON'), value: 'json' },
  { content: t('knowledgeEditor.faqImport.downloadExampleCSV'), value: 'csv' },
  { content: t('knowledgeEditor.faqImport.downloadExampleExcel'), value: 'excel' },
])

// 示例数据
const exampleData: FAQEntryPayload[] = [
  {
    standard_question: '什么是 WeKnora？',
    answers: ['WeKnora 是一个智能知识库管理系统', '它支持多种知识库类型和导入方式'],
    similar_questions: ['WeKnora 是什么？', '介绍一下 WeKnora'],
    negative_questions: ['这不是 WeKnora', '与 WeKnora 无关'],
  },
  {
    standard_question: '如何创建知识库？',
    answers: ['点击"新建知识库"按钮', '选择知识库类型并填写相关信息', '完成创建后即可开始使用'],
    similar_questions: ['怎么创建知识库？', '如何新建知识库？'],
    negative_questions: [],
  },
]

// 下载示例文件
const handleDownloadExample = (data: { value: string }) => {
  const { value } = data
  switch (value) {
    case 'json':
      downloadJSONExample()
      break
    case 'csv':
      downloadCSVExample()
      break
    case 'excel':
      downloadExcelExample()
      break
  }
}

// 下载 JSON 示例
const downloadJSONExample = () => {
  const jsonStr = JSON.stringify(exampleData, null, 2)
  const blob = new Blob([jsonStr], { type: 'application/json;charset=utf-8' })
  const url = URL.createObjectURL(blob)
  const link = document.createElement('a')
  link.href = url
  link.download = 'faq_example.json'
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
  URL.revokeObjectURL(url)
}

// 下载 CSV 示例
const downloadCSVExample = () => {
  const headers = ['分类(必填)', '问题(必填)', '相似问题(选填-多个用##分隔)', '反例问题(选填-多个用##分隔)', '机器人回答(必填-多个用##分隔)', '是否全部回复(选填-默认FALSE)', '是否停用(选填-默认FALSE)', '是否禁止被推荐(选填-默认False 可被推荐)']
  const rows = exampleData.map((item) => {
    return [
      '', // 分类
      item.standard_question,
      item.similar_questions.join('##'),
      item.negative_questions.join('##'),
      item.answers.join('##'),
      'FALSE', // 是否全部回复
      'FALSE', // 是否停用
      'FALSE', // 是否禁止被推荐
    ]
  })
  const csvContent = [
    headers.join('\t'), // 使用制表符分隔
    ...rows.map((row) => row.map((cell) => {
      // 如果包含制表符、换行符或引号，需要用引号包裹
      if (cell.includes('\t') || cell.includes('\n') || cell.includes('"')) {
        return `"${cell.replace(/"/g, '""')}"`
      }
      return cell
    }).join('\t')),
  ].join('\n')
  const blob = new Blob(['\ufeff' + csvContent], { type: 'text/csv;charset=utf-8' })
  const url = URL.createObjectURL(blob)
  const link = document.createElement('a')
  link.href = url
  link.download = 'faq_example.csv'
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
  URL.revokeObjectURL(url)
}

// 下载 Excel 示例
const downloadExcelExample = () => {
  const worksheet = XLSX.utils.json_to_sheet(
    exampleData.map((item) => ({
      '分类(必填)': '',
      '问题(必填)': item.standard_question,
      '相似问题(选填-多个用##分隔)': item.similar_questions.join('##'),
      '反例问题(选填-多个用##分隔)': item.negative_questions.join('##'),
      '机器人回答(必填-多个用##分隔)': item.answers.join('##'),
      '是否全部回复(选填-默认FALSE)': 'FALSE',
      '是否停用(选填-默认FALSE)': 'FALSE',
      '是否禁止被推荐(选填-默认False 可被推荐)': 'FALSE',
    })),
  )
  const workbook = XLSX.utils.book_new()
  XLSX.utils.book_append_sheet(workbook, worksheet, 'FAQ')
  XLSX.writeFile(workbook, 'faq_example.xlsx')
}

watch(
  () => props.kbId,
  async (newKbId) => {
    currentPage = 1
    hasMore.value = true
    selectedTagId.value = ''
    cancelCreateTag()
    cancelEditTag()
    tagSearchQuery.value = ''

    if (!newKbId) {
      kbInfo.value = null
      // kbId变化时，清除之前的任务状态
      stopPolling()
      importState.taskId = null
      importState.taskStatus = null
      clearTaskIdFromStorage()
      return
    }

    const info = await loadKnowledgeInfo(newKbId)
    if (!info || info.type !== 'faq') {
      return
    }

    loadEntries()
    loadTags(true)
    // 恢复导入任务状态（如果存在）
    await restoreImportTask()
  },
  { immediate: true },
)

watch(selectedTagId, (newVal, oldVal) => {
  if (oldVal === undefined) return
  if (newVal !== oldVal) {
    currentPage = 1
    entries.value = []
    selectedRowKeys.value = []
    loadEntries()
  }
})

watch(tagSearchQuery, (newVal, oldVal) => {
  if (newVal === oldVal) return
  if (tagSearchDebounce) {
    clearTimeout(tagSearchDebounce)
  }
  tagSearchDebounce = window.setTimeout(() => {
    loadTags(true)
  }, 300)
})

// 监听FAQ搜索关键词变化
watch(entrySearchKeyword, (newVal, oldVal) => {
  if (newVal === oldVal) return
  if (entrySearchDebounce) {
    clearTimeout(entrySearchDebounce)
  }
  entrySearchDebounce = window.setTimeout(() => {
    loadEntries()
  }, 300)
})

const handleSearch = async () => {
  if (!searchForm.query.trim()) {
    MessagePlugin.warning(t('knowledgeEditor.faq.queryPlaceholder'))
    return
  }

  searching.value = true
  hasSearched.value = true
  try {
    const res = await searchFAQEntries(props.kbId, {
      query_text: searchForm.query.trim(),
      vector_threshold: searchForm.vectorThreshold,
      match_count: searchForm.matchCount,
    })
    const results = (res.data || []).map((entry: FAQEntry) => ({
      ...entry,
      similarCollapsed: true,  // 相似问默认折叠
      negativeCollapsed: true,  // 反例默认折叠
      answersCollapsed: true,   // 答案默认折叠
      expanded: false,
    })) as FAQEntry[]
    
    // 按score从大到小排序
    searchResults.value = results.sort((a, b) => (b.score || 0) - (a.score || 0))
  } catch (error: any) {
    MessagePlugin.error(error?.message || t('common.operationFailed'))
    searchResults.value = []
  } finally {
    searching.value = false
  }
}

const getMatchTypeLabel = (matchType?: string) => {
  if (!matchType) return ''
  if (matchType === 'embedding') {
    return t('knowledgeEditor.faq.matchTypeEmbedding')
  }
  if (matchType === 'keywords') {
    return t('knowledgeEditor.faq.matchTypeKeywords')
  }
  return matchType
}

const toggleResult = (result: FAQEntry) => {
  result.expanded = !result.expanded
}

// 防抖函数
let arrangeCardsTimer: ReturnType<typeof setTimeout> | null = null
const debounceArrangeCards = (delay = 100) => {
  if (arrangeCardsTimer) {
    clearTimeout(arrangeCardsTimer)
  }
  arrangeCardsTimer = setTimeout(() => {
    arrangeCards()
    arrangeCardsTimer = null
  }, delay)
}

// 瀑布流布局函数 - 优化版本，避免闪烁
const arrangeCards = () => {
  if (!cardListRef.value) return
  
  const cards = cardListRef.value.querySelectorAll('.faq-card') as NodeListOf<HTMLElement>
  if (cards.length === 0) return
  
  // 获取容器宽度和列数
  const containerWidth = cardListRef.value.offsetWidth
  const gap = 12 // 与 CSS gap 保持一致
  let columnCount = 1
  
  // 根据容器宽度计算列数（增加每行的卡片数量）
  if (containerWidth >= 2560) columnCount = 12
  else if (containerWidth >= 1920) columnCount = 10
  else if (containerWidth >= 1536) columnCount = 8
  else if (containerWidth >= 1280) columnCount = 6
  else if (containerWidth >= 1024) columnCount = 5
  else if (containerWidth >= 768) columnCount = 4
  else if (containerWidth >= 640) columnCount = 3
  
  const columnWidth = (containerWidth - (gap * (columnCount - 1))) / columnCount
  
  // 初始化每列的高度数组
  const columnHeights = new Array(columnCount).fill(0)
  
  // 使用 requestAnimationFrame 优化性能
  requestAnimationFrame(() => {
    // 先设置宽度，保持当前位置不变
    cards.forEach((card) => {
      // 确保卡片是绝对定位
      if (card.style.position !== 'absolute') {
        card.style.position = 'absolute'
      }
      // 设置宽度以便正确计算高度
      card.style.width = `${columnWidth}px`
    })
    
    // 等待浏览器重新计算布局
    requestAnimationFrame(() => {
      // 计算所有卡片的高度（不改变位置）
      const cardHeights: number[] = []
      cards.forEach((card) => {
        const height = card.offsetHeight || card.getBoundingClientRect().height
        cardHeights.push(height)
      })
      
      // 计算新位置
      const newPositions: Array<{ top: number; left: number }> = []
      cardHeights.forEach((height) => {
        const shortestColumnIndex = columnHeights.indexOf(Math.min(...columnHeights))
        const top = columnHeights[shortestColumnIndex]
        const left = shortestColumnIndex * (columnWidth + gap)
        
        newPositions.push({ top, left })
        columnHeights[shortestColumnIndex] += height + gap
      })
      
      // 批量更新所有卡片位置，使用CSS过渡实现平滑移动
      cards.forEach((card, index) => {
        const { top, left } = newPositions[index]
        const currentTop = parseFloat(card.style.top) || 0
        const currentLeft = parseFloat(card.style.left) || 0
        
        // 如果位置发生变化，添加过渡效果
        if (Math.abs(currentTop - top) > 1 || Math.abs(currentLeft - left) > 1) {
          // 使用 will-change 提示浏览器优化
          card.style.willChange = 'top, left'
          card.style.transition = 'top 0.3s cubic-bezier(0.4, 0, 0.2, 1), left 0.3s cubic-bezier(0.4, 0, 0.2, 1)'
        }
        
        card.style.position = 'absolute'
        card.style.top = `${top}px`
        card.style.left = `${left}px`
        card.style.width = `${columnWidth}px`
      })
      
      // 设置容器高度
      const maxHeight = Math.max(...columnHeights)
      if (cardListRef.value) {
        cardListRef.value.style.height = `${maxHeight}px`
        cardListRef.value.style.position = 'relative'
      }
      
      // 动画完成后移除过渡和 will-change，避免影响后续交互
      setTimeout(() => {
        cards.forEach((card) => {
          card.style.transition = ''
          card.style.willChange = ''
        })
      }, 300)
    })
  })
}

// 监听窗口大小变化（使用防抖）
let resizeTimer: ReturnType<typeof setTimeout> | null = null
const handleResize = () => {
  if (resizeTimer) {
    clearTimeout(resizeTimer)
  }
  resizeTimer = setTimeout(() => {
    arrangeCards()
    // 窗口变大时可能需要加载更多，延迟执行确保布局完成
    setTimeout(() => {
      checkAndLoadMore()
    }, 350)
    resizeTimer = null
  }, 150)
}

onMounted(async () => {
  loadKnowledgeList()
  window.addEventListener('resize', handleResize)
  window.addEventListener('faqMenuAction', handleFaqMenuAction as EventListener)
  // 如果已有kbId，恢复导入任务状态
  if (props.kbId) {
    await restoreImportTask()
  }
  // 主动触发一次选中数量事件，确保左侧菜单能接收到初始状态
  nextTick(() => {
    const count = selectedRowKeys.value.length
    const selectedEntries = entries.value.filter(entry => selectedRowKeys.value.includes(entry.id))
    const enabledCount = selectedEntries.filter(entry => entry.is_enabled !== false).length
    const disabledCount = count - enabledCount
    window.dispatchEvent(new CustomEvent('faqSelectionChanged', {
      detail: { 
        count,
        enabledCount,
        disabledCount
      }
    }))
  })
})

onUnmounted(() => {
  window.removeEventListener('resize', handleResize)
  window.removeEventListener('faqMenuAction', handleFaqMenuAction as EventListener)
  if (arrangeCardsTimer) {
    clearTimeout(arrangeCardsTimer)
  }
  if (resizeTimer) {
    clearTimeout(resizeTimer)
  }
})

// 监听 entries 变化，重新布局
watch(() => entries.value.length, () => {
  nextTick(() => {
    arrangeCards()
  })
})

// 监听折叠状态变化，重新布局（使用防抖和动画完成后的回调）
watch(() => entries.value.map(e => ({
  id: e.id,
  similarCollapsed: e.similarCollapsed,
  negativeCollapsed: e.negativeCollapsed,
  answersCollapsed: e.answersCollapsed
})), () => {
  // 使用 nextTick 确保 DOM 更新
  nextTick(() => {
    // 等待一个渲染帧，让高度变化生效
    requestAnimationFrame(() => {
      // 再等待一个渲染帧，确保高度计算准确
      requestAnimationFrame(() => {
        // 等待 Transition 动画完成后再布局（slide-down 动画时长约 200ms）
        // 使用防抖避免频繁调用
        debounceArrangeCards(250)
      })
    })
  })
}, { deep: true })
</script>

<style lang="less">
.tag-more-popup {
  z-index: 99 !important;

  .t-popup__content {
    padding: 4px 0 !important;
    margin-top: 4px !important;
    min-width: 120px;
  }
}

/* 面包屑下拉菜单优化 */
.t-popup__content {
  .t-dropdown__menu {
    background: #ffffff;
    border: 1px solid #e7e9eb;
    border-radius: 10px;
    box-shadow: 0 6px 28px rgba(15, 23, 42, 0.08);
    padding: 6px;
    min-width: 150px;
    max-width: 200px;
  }

  .t-dropdown__item {
    padding: 8px 12px;
    border-radius: 6px;
    margin: 2px 0;
    transition: all 0.12s ease;
    font-size: 13px;
    color: #0f172a;
    cursor: pointer;
    min-width: auto !important;
    max-width: 100% !important;
    display: flex !important;
    align-items: center;
    width: 100%;

    &:hover {
      background: #f6f8f7;
      color: #10b981;
    }

    .t-dropdown__item-icon {
      flex-shrink: 0;
      margin-right: 8px;
      color: inherit;
      display: flex;
      align-items: center;
      
      .t-icon {
        font-size: 16px;
      }
    }

    .t-dropdown__item-text {
      color: inherit !important;
      font-size: 13px !important;
      line-height: 1.5 !important;
      white-space: nowrap !important;
      overflow: hidden !important;
      text-overflow: ellipsis !important;
      flex: 1;
      min-width: 0;
      display: block;
    }
  }
}
</style>
<style scoped lang="less">
.faq-manager {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.15s ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

.faq-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.faq-main {
  display: flex;
  gap: 16px;
  flex: 1;
  min-height: 0;
}

.faq-tag-panel {
  width: 230px;
  background: #fff;
  border: 1px solid #e7ebf0;
  border-radius: 12px;
  padding: 16px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  max-height: 100%;
  min-height: 0;
  overflow: hidden;

  // t-loading 包裹容器需要撑满剩余空间
  > .t-loading__parent,
  > .t-loading {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }

  .sidebar-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
    color: #1d2129;

    .sidebar-title {
      display: flex;
      align-items: baseline;
      gap: 4px;
      font-weight: 600;

      .sidebar-count {
        font-size: 12px;
        color: #86909c;
      }
    }

    .sidebar-actions {
      display: flex;
      gap: 8px;
      color: #c9ced6;

      .create-tag-btn {
        width: 28px;
        height: 28px;
        padding: 0;
        border-radius: 6px;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 18px;
        font-weight: 600;
        color: #00a870;
        line-height: 1;
        transition: background 0.2s ease, color 0.2s ease;

        &:hover {
          background: #f3f5f7;
          color: #05a04f;
        }
      }

      .create-tag-plus {
        line-height: 1;
      }

      .sidebar-action-icon {
        width: 28px;
        height: 28px;
        border-radius: 6px;
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
        transition: background 0.2s ease, color 0.2s ease;

        &:hover {
          background: #f3f5f7;
          color: #00a870;
        }
      }
    }
  }

  .tag-search-bar {
    margin-bottom: 12px;

    :deep(.t-input) {
      font-size: 12px;
      background-color: #f7f9fc;
      border-color: #e5e9f2;
    }
  }

  .faq-tag-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;

    .tag-loading-more {
      padding: 12px 0;
      display: flex;
      justify-content: center;
      flex-shrink: 0;
    }

    .faq-tag-item {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 8px 10px;
      border-radius: 6px;
      color: #4e5969;
      cursor: pointer;
      transition: all 0.2s ease;
      font-size: 13px;

      .faq-tag-left {
        display: flex;
        align-items: center;
        gap: 8px;
        min-width: 0;
        flex: 1;

        .t-icon {
          flex-shrink: 0;
          color: #86909c;
          font-size: 16px;
          transition: color 0.2s ease;
        }
      }

      .tag-name {
        flex: 1;
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        font-weight: 400;
      }

      .faq-tag-right {
        display: flex;
        align-items: center;
        gap: 6px;
        margin-left: 8px;
        min-width: 0;
        flex-shrink: 0;
      }

      .faq-tag-count {
        font-size: 12px;
        color: #86909c;
        font-weight: 500;
        padding: 2px 6px;
        border-radius: 10px;
        background: #f7f9fc;
        transition: all 0.2s ease;
      }

      &:hover {
        background: #f7f9fc;
        color: #1d2129;

        .faq-tag-left .t-icon {
          color: #4e5969;
        }

        .faq-tag-count {
          background: #e5e9f2;
          color: #4e5969;
        }
      }

      &.active {
        background: #e6f7ec;
        color: #00a870;
        font-weight: 500;

        .faq-tag-left .t-icon {
          color: #00a870;
        }

        .faq-tag-count {
          background: #b8f0d3;
          color: #00a870;
          font-weight: 600;
        }

        &:hover {
          background: #d4f4e3;
        }
      }

      &.editing {
        background: transparent;
        border: none;
      }

      &.tag-editing {
        cursor: default;
        padding-right: 8px;
        background: transparent;
        border: none;

        .tag-edit-input {
          flex: 1;
        }
      }

      &.tag-editing .tag-edit-input {
        width: 100%;
      }

      .tag-inline-actions {
        display: flex;
        gap: 4px;
        margin-left: auto;

        :deep(.t-button) {
          padding: 0 4px;
          height: 24px;
        }

        :deep(.tag-action-btn) {
          border-radius: 4px;
          transition: all 0.2s ease;

          .t-icon {
            font-size: 14px;
          }
        }

        :deep(.tag-action-btn.confirm) {
          background: #eefcf5;
          color: #059669;

          &:hover {
            background: #d9f7e9;
            color: #047857;
          }
        }

        :deep(.tag-action-btn.cancel) {
          background: #f9fafb;
          color: #6b7280;

          &:hover {
            background: #f3f4f6;
            color: #4b5563;
          }
        }
      }

      .tag-edit-input {
        flex: 1;
        min-width: 0;
        max-width: 100%;

        :deep(.t-input) {
          font-size: 12px;
          background-color: transparent;
          border: none;
          border-bottom: 1px solid #d0d5dd;
          border-radius: 0;
          box-shadow: none;
          padding-left: 0;
          padding-right: 0;
        }

        :deep(.t-input__wrap) {
          background-color: transparent;
          border: none;
          border-bottom: 1px solid #d0d5dd;
          border-radius: 0;
          box-shadow: none;
        }

        :deep(.t-input__inner) {
          padding-left: 0;
          padding-right: 0;
          color: #1d2129;
          caret-color: #1d2129;
        }

        :deep(.t-input:hover),
        :deep(.t-input.t-is-focused),
        :deep(.t-input__wrap:hover),
        :deep(.t-input__wrap.t-is-focused) {
          border-bottom-color: #00a870;
        }
      }

      .tag-more-btn {
        width: 24px;
        height: 24px;
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: 4px;
        color: #86909c;
        transition: all 0.2s ease;
        opacity: 0.6;

        &:hover {
          background: #f3f5f7;
          color: #4e5969;
          opacity: 1;
        }
      }


      .tag-more {
        display: flex;
        align-items: center;
      }
    }

    .tag-empty-state {
      text-align: center;
      padding: 12px 8px;
      color: #a1a7b3;
      font-size: 12px;
    }
  }
}

.faq-card-area {
  flex: 1;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.faq-search-bar {
  padding: 0px 0px 10px 0px;
  flex-shrink: 0;

  :deep(.t-input) {
    font-size: 13px;
    background-color: #f7f9fc;
    border-color: #e5e9f2;
    border-radius: 6px;

    &:hover,
    &:focus,
    &.t-is-focused {
      background-color: #fff;
      border-color: #00a870;
    }
  }
}

:deep(.tag-menu) {
  display: flex;
  flex-direction: column;
}

:deep(.tag-menu-item) {
  display: flex;
  align-items: center;
  padding: 8px 16px;
  cursor: pointer;
  transition: all 0.2s ease;
  color: #000000e6;
  font-family: "PingFang SC";
  font-size: 14px;
  font-weight: 400;

  .menu-icon {
    margin-right: 8px;
    font-size: 16px;
  }

  &:hover {
    background: #f5f5f5;
    color: #000000e6;
  }

  &.danger {
    color: #000000e6;

    &:hover {
      background: #fff1f0;
      color: #fa5151;

      .menu-icon {
        color: #fa5151;
      }
    }
  }
}

.faq-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
  padding: 0 0 16px;
  margin-bottom: 20px;
  border-bottom: 1px solid #e7ebf0;
  flex-shrink: 0;
}

// 导入进度条样式（显示在列表页面顶部）
.faq-import-progress-bar {
  margin-bottom: 16px;
  background: linear-gradient(135deg, #f8fffe 0%, #f5fff9 100%);
  border: 1px solid #d4f0e0;
  border-radius: 10px;
  padding: 14px 18px;
  box-shadow: 0 2px 12px rgba(0, 168, 112, 0.08);

  .progress-bar-content {
    display: flex;
    flex-direction: column;
    gap: 10px;
  }

  .progress-bar-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 14px;
    color: #000000e6;

    .progress-left {
      display: flex;
      align-items: center;
      gap: 10px;
    }

    .progress-right {
      display: flex;
      align-items: center;
      gap: 16px;
    }

    .progress-icon {
      flex-shrink: 0;

      &.icon-loading {
        animation: rotate 1s linear infinite;
        color: #00a870;
      }

      &.icon-success {
        color: #00a870;
      }

      &.icon-error {
        color: #fa5151;
      }
    }

    .progress-title {
      font-weight: 600;
      font-size: 14px;
      color: #1d2129;
    }

    .progress-count {
      color: #4e5969;
      font-size: 13px;
      font-weight: 500;
      background: rgba(0, 168, 112, 0.1);
      padding: 2px 10px;
      border-radius: 12px;
    }

    .progress-close-btn {
      flex-shrink: 0;
      padding: 4px;
      margin-left: 4px;
      border-radius: 4px;
      
      &:hover {
        background: rgba(0, 0, 0, 0.06);
      }
    }
  }

  .progress-bar {
    margin: 0;
    width: 100%;
    
    :deep(.t-progress) {
      width: 100%;
    }
    
    :deep(.t-progress__bar) {
      width: 100%;
      height: 8px;
      border-radius: 4px;
      background: rgba(0, 168, 112, 0.15);
    }
    
    :deep(.t-progress__inner) {
      border-radius: 4px;
    }
  }

  .progress-error {
    margin: 0;
    font-size: 13px;
    color: #fa5151;
    line-height: 1.5;
    background: rgba(250, 81, 81, 0.08);
    padding: 8px 12px;
    border-radius: 6px;
  }
}

@keyframes rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

  .faq-header-title {
    display: flex;
    flex-direction: column;
    gap: 4px;
  }

  .faq-title-row {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
  }

  .faq-breadcrumb {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 0;
    font-size: 20px;
    font-weight: 600;
    color: #1d2129;
  }

  .breadcrumb-link {
    border: none;
    background: transparent;
    padding: 4px 8px;
    margin: -4px -8px;
    font: inherit;
    color: #4e5969;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    border-radius: 6px;
    transition: all 0.12s ease;

    &:hover:not(:disabled) {
      color: #10b981;
      background: #f6f8f7;
    }

    &:disabled {
      cursor: not-allowed;
      color: #c9ced6;
    }

    &.dropdown {
      padding-right: 6px;
      
      :deep(.t-icon) {
        font-size: 14px;
        transition: transform 0.12s ease;
      }

      &:hover:not(:disabled) {
        :deep(.t-icon) {
          transform: translateY(1px);
        }
      }
    }
  }

  .breadcrumb-separator {
    font-size: 14px;
    color: #c9ced6;
  }

  .breadcrumb-current {
    color: #1d2129;
    font-weight: 600;
  }

  h2 {
    margin: 0;
    color: #1d2129;
    font-family: "PingFang SC";
    font-size: 24px;
    font-weight: 600;
    line-height: 32px;
  }

  .faq-subtitle {
    margin: 0;
    color: #00000099;
    font-family: "PingFang SC";
    font-size: 14px;
    font-weight: 400;
    line-height: 20px;
  }


.tag-filter-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;

  .tag-filter-label {
    color: #6B7280;
    font-size: 14px;
  }
}


.kb-settings-button {
  width: 30px;
  height: 30px;
  border: none;
  border-radius: 50%;
  background: #f5f6f8;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #6b7280;
  cursor: pointer;
  transition: all 0.2s ease;
  padding: 0;

  &:hover:not(:disabled) {
    background: #e6f7ec;
    color: #07c05f;
  }

  &:disabled {
    cursor: not-allowed;
    opacity: 0.4;
  }

  :deep(.t-icon) {
    font-size: 18px;
  }
}

// 滚动容器
.faq-scroll-container {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  padding-right: 4px;
}

// 卡片列表样式 - 使用绝对定位实现瀑布流，下一行补齐上一行空缺
.faq-card-list {
  position: relative;
  width: 100%;
  min-width: 0;
}

.faq-card {
  border: 1px solid #E7E7E7;
  border-radius: 12px;
  background: #fff;
  padding: 12px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
  cursor: pointer;
  transition: border-color 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease;
  box-sizing: border-box;
  height: fit-content; // 高度根据内容自适应
  // 注意：top 和 left 的 transition 由 JS 动态控制，避免与布局动画冲突

  &:hover {
    border-color: #07C05F;
    box-shadow: 0 2px 8px rgba(7, 192, 95, 0.1);
  }

  &.selected {
    border-color: #07C05F;
    background: #F0FDF4;
    box-shadow: 0 2px 8px rgba(7, 192, 95, 0.15);
  }
}

.faq-card-header {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-bottom: 12px;
  border-bottom: 1px solid #F3F4F6;
  position: relative;
}

.faq-header-top {
  display: flex;
  align-items: flex-start;
  gap: 12px;
}

.faq-card-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
  flex-shrink: 0;
}

.faq-header-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding-top: 6px;
  border-top: 1px dashed #F3F4F6;
}

.faq-meta-item {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 999px;
  background: #F9FAFB;
  border: 1px solid #EEF2F7;

  .meta-label {
    font-size: 12px;
    color: #6B7280;
    font-weight: 500;
  }

  .meta-value {
    font-size: 13px;
    color: #111827;
    font-weight: 600;
  }
}

.faq-card-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 16px;
  margin: 0 -16px -12px;
  background: rgba(48, 50, 54, 0.02);
  border-top: 1px solid #f5f5f5;
  flex-wrap: nowrap;
}

.faq-card-status {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  margin-left: auto;
}

.status-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 999px;
  background: #F9FAFB;
  border: 1px solid #EEF2F7;
  font-size: 12px;
  color: #4B5563;
  font-family: "PingFang SC";

  .status-icon {
    font-size: 14px;
    color: #9CA3AF;

    &.warning {
      color: #F97316;
    }

    &.success {
      color: #10B981;
    }
  }
}

.status-item-compact {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 4px;
  border-radius: 4px;
  background: transparent;
  border: none;
  cursor: pointer;
  transition: all 0.2s ease;

  &:hover {
    background: rgba(0, 0, 0, 0.04);
  }

  .status-icon {
    font-size: 16px;
    flex-shrink: 0;

    &.warning {
      color: #F97316;
    }

    &.success {
      color: #10B981;
    }
  }

  :deep(.t-switch) {
    flex-shrink: 0;
  }
}

.faq-card-tag {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  flex: 1;
  min-width: 0;

  :deep(.t-tag) {
    display: inline-flex;
    align-items: center;
    cursor: pointer;
    max-width: 140px;
    height: 22px;
    border-radius: 4px;
    border-color: #e5e7eb;
    color: #00000066;
    padding: 0 8px;
    background: #3032360f;
    font-size: 12px;
    font-weight: 400;
    font-family: "PingFang SC";
    transition: all 0.2s ease;

    &:hover {
      border-color: #07c05f;
      color: #059669;
      background: #ecfdf5;
    }
  }
}

.faq-tag-chip {
  display: inline-flex;
  align-items: center;
  cursor: pointer;

  .tag-text {
    max-width: 120px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 12px;
    font-weight: 400;
    color: #00000066;
  }
}

.card-more-btn {
  display: flex;
  width: 28px;
  height: 28px;
  justify-content: center;
  align-items: center;
  border-radius: 6px;
  cursor: pointer;
  flex-shrink: 0;
  opacity: 0.6;

  &:hover {
    background: #F3F4F6;
    opacity: 1;
  }

  &.mobile {
    display: none;
  }

  .more-icon {
    width: 16px;
    height: 16px;
  }
}

.card-menu {
  display: flex;
  flex-direction: column;
}

.card-menu-item {
  display: flex;
  align-items: center;
  padding: 8px 16px;
  cursor: pointer;
  transition: all 0.2s ease;
  color: #000000e6;
  font-family: "PingFang SC";
  font-size: 14px;
  font-weight: 400;

  .menu-icon {
    margin-right: 8px;
    font-size: 16px;
    flex-shrink: 0;
  }

  &:hover {
    background: #f5f5f5;
    color: #000000e6;
  }

  &.danger {
    color: #000000e6;

    &:hover {
      background: #fff1f0;
      color: #fa5151;

      .menu-icon {
        color: #fa5151;
      }
    }
  }
}

.faq-question {
  flex: 1;
  color: #111827;
  font-family: "PingFang SC";
  font-size: 15px;
  font-weight: 600;
  line-height: 1.5;
  word-break: break-word;
  min-width: 0;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
}

.faq-card-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1;
  min-width: 0;
  overflow: hidden;
  contain: layout; // 优化渲染性能
}

.faq-section {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
  overflow: hidden;

  .faq-section-label {
    color: #6B7280;
    font-family: "PingFang SC";
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 2px;

    &::before {
      content: '';
      width: 3px;
      height: 12px;
      background: #07C05F;
      border-radius: 2px;
      flex-shrink: 0;
    }

    &.clickable {
      cursor: pointer;
      user-select: none;
      padding: 2px 0;
      border-radius: 4px;

      &:hover {
        color: #111827;
        background: #F9FAFB;
        padding-left: 4px;
        padding-right: 4px;
        margin-left: -4px;
        margin-right: -4px;
      }
    }

    .collapse-icon {
      font-size: 14px;
      color: #9CA3AF;
      flex-shrink: 0;
      margin-left: auto; // 让箭头靠右对齐
    }

    .section-count {
      color: #9CA3AF;
      font-weight: 400;
      margin-left: 4px;
    }
  }

  &.answers .faq-section-label::before {
    background: #07C05F;
  }

  &.similar .faq-section-label::before {
    background: #3B82F6;
  }

  &.negative .faq-section-label::before {
    background: #F59E0B;
  }
}

.faq-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  min-height: 20px;
  min-width: 0;
  width: 100%;
  overflow: hidden;
  contain: layout style paint; // 优化渲染性能
  
  // 确保每个标签都有最大宽度限制
  > * {
    max-width: 100%;
    min-width: 0;
    flex: 0 1 auto;
  }
  
  // 当标签单独一行时，限制最大宽度
  > *:first-child:last-child {
    max-width: 100%;
  }
}

.question-tag {
  font-size: 12px;
  padding: 4px 10px;
  max-width: 100%;
  min-width: 0;
  border-radius: 6px;
  font-family: "PingFang SC";
  flex: 0 1 auto;
  
  :deep(.t-tag) {
    max-width: 100% !important;
    min-width: 0 !important;
    width: auto !important;
    display: inline-flex !important;
    align-items: center;
    vertical-align: middle;
    overflow: hidden !important;
    box-sizing: border-box;
    background: #F9FAFB;
    border-color: #E5E7EB;
    color: #374151;
  }
  
  // 针对TDesign tag内部的span元素
  :deep(.t-tag span),
  :deep(.t-tag > span) {
    display: block !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    white-space: nowrap !important;
    max-width: 100% !important;
    width: auto !important;
    line-height: 1.4;
    min-width: 0 !important;
  }
}

// 确保 tag 本身不会超出容器
.faq-tags :deep(.t-tag) {
  max-width: 100%;
  min-width: 0;
  flex-shrink: 1;
}

.faq-tags :deep(.faq-tag-wrapper) {
  max-width: 100%;
  min-width: 0;
  flex-shrink: 1;
}

.empty-tip {
  color: #9CA3AF;
  font-size: 12px;
  font-style: italic;
  padding: 8px 0;
  font-family: "PingFang SC";
}


.faq-load-more,
.faq-no-more {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 24px 16px;
  color: #6B7280;
  font-size: 13px;
  font-family: "PingFang SC";
}

.faq-no-more {
  color: #9CA3AF;
  font-style: italic;
}

// 空状态样式
.faq-empty-state {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 400px;
  padding: 60px 20px;

  .empty-content {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 16px;
    text-align: center;
    max-width: 400px;
  }

  .empty-icon {
    color: #D1D5DB;
    opacity: 0.6;
  }

  .empty-text {
    color: #111827;
    font-family: "PingFang SC";
    font-size: 18px;
    font-weight: 600;
    line-height: 28px;
  }

  .empty-desc {
    color: #6B7280;
    font-family: "PingFang SC";
    font-size: 14px;
    font-weight: 400;
    line-height: 22px;
  }
}

// 导入对话框样式 - 与创建知识库弹窗风格一致
.faq-import-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  backdrop-filter: blur(4px);
}

.faq-import-modal {
  position: relative;
  width: 100%;
  max-width: 600px;
  max-height: 90vh;
  background: #ffffff;
  border-radius: 12px;
  box-shadow: 0 6px 28px rgba(15, 23, 42, 0.08);
  overflow: hidden;
  display: flex;
  flex-direction: column;

  .close-btn {
    position: absolute;
    top: 20px;
    right: 20px;
    width: 32px;
    height: 32px;
    border: none;
    background: #f5f5f5;
    border-radius: 6px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #666;
    transition: all 0.2s ease;
    z-index: 10;

    &:hover {
      background: #e5e5e5;
      color: #000;
    }
  }
}

.faq-import-container {
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden;
}

.faq-import-header {
  padding: 24px 24px 16px;
  border-bottom: 1px solid #e5e5e5;
  flex-shrink: 0;

  .import-title {
    margin: 0;
    font-family: "PingFang SC";
    font-size: 18px;
    font-weight: 600;
    color: #000000e6;
  }
}

.faq-import-content {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 24px;
  min-height: 0;
  max-height: calc(90vh - 140px); // 减去 header 和 footer 的高度
  
  // 自定义滚动条
  &::-webkit-scrollbar {
    width: 6px;
  }

  &::-webkit-scrollbar-track {
    background: #f5f5f5;
    border-radius: 3px;
  }

  &::-webkit-scrollbar-thumb {
    background: #d0d0d0;
    border-radius: 3px;
    transition: background 0.2s;

    &:hover {
      background: #07C05F;
    }
  }
}

.faq-import-footer {
  padding: 16px 24px;
  border-top: 1px solid #e5e5e5;
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  flex-shrink: 0;
}

// 导入表单项
.import-form-item {
  margin-bottom: 24px;

  &:last-child {
    margin-bottom: 0;
  }
}

// 文件标签行
.file-label-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
  gap: 12px;
}

// 下载示例按钮
.download-example-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: "PingFang SC";
  font-size: 13px;
  font-weight: 500;
  padding: 6px 14px;
  border-radius: 6px;
  border: 1px solid #E7E7E7;
  background: #ffffff;
  color: #333333;
  transition: all 0.2s ease;
  cursor: pointer;
  white-space: nowrap;

  &:hover {
    border-color: #07C05F;
    color: #07C05F;
    background: #f0fdf4;
  }

  &:active {
    background: #e0f9ea;
  }

  :deep(.t-icon) {
    font-size: 16px;
  }
}

// 导入表单标签
.import-form-label {
  display: block;
  margin-bottom: 0;
  font-family: "PingFang SC";
  font-size: 14px;
  font-weight: 500;
  color: #333333;
  letter-spacing: -0.2px;
  flex: 1;

  &.required::after {
    content: '*';
    color: #FA5151;
    margin-left: 4px;
    font-weight: 600;
  }
}

// 单选按钮组样式 - 符合项目主题风格
:deep(.import-radio-group) {
  .t-radio-group--filled {
    background: #f5f5f5;
    border-radius: 6px;
    padding: 2px;
  }
  
  .t-radio-button {
    font-family: "PingFang SC";
    font-size: 14px;
    border-color: #d9d9d9;
    transition: all 0.2s ease;

    &:hover:not(.t-is-disabled) {
      border-color: #07c05f;
      color: #07c05f;
    }

    &.t-is-checked {
      background: #07c05f;
      border-color: #07c05f;
      color: #fff;
      font-weight: 500;

      &:hover:not(.t-is-disabled) {
        background: #05a04f;
        border-color: #05a04f;
        color: #fff;
      }
    }
  }
}

// 文件上传包装器
.file-upload-wrapper {
  width: 100%;
}

// 隐藏的文件输入
.file-input-hidden {
  position: absolute;
  width: 0;
  height: 0;
  opacity: 0;
  overflow: hidden;
  pointer-events: none;
}

// 文件上传区域
.file-upload-area {
  position: relative;
  width: 100%;
  min-height: 120px;
  border: 2px dashed #d9d9d9;
  border-radius: 8px;
  background: #fafafa;
  cursor: pointer;
  transition: all 0.3s ease;
  display: flex;
  align-items: center;
  justify-content: center;

  &:hover {
    border-color: #07C05F;
    background: #f0fdf4;
  }

  &.has-file {
    border-color: #07C05F;
    background: #f0fdf4;
    border-style: solid;
  }
}

// 文件上传内容
.file-upload-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  text-align: center;
}

.upload-icon {
  color: #07C05F;
  transition: transform 0.2s ease;
}

.file-upload-area:hover .upload-icon {
  transform: translateY(-2px);
}

.upload-text {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.upload-primary-text {
  font-family: "PingFang SC";
  font-size: 14px;
  font-weight: 500;
  color: #333333;
}

.upload-secondary-text {
  font-family: "PingFang SC";
  font-size: 12px;
  color: #666666;
}

.upload-file-name {
  font-family: "PingFang SC";
  font-size: 14px;
  font-weight: 500;
  color: #07C05F;
  word-break: break-all;
}

// 导入表单提示
.import-form-tip {
  margin-top: 8px;
  font-family: "PingFang SC";
  font-size: 12px;
  color: #00000066;
  line-height: 18px;
}

// 预览区域
.import-preview {
  margin-top: 20px;
  padding: 16px;
  background: #fafafa;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
}

.preview-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
  padding-bottom: 12px;
  border-bottom: 1px solid #e5e7eb;
}

.preview-icon {
  color: #07C05F;
  flex-shrink: 0;
}

.preview-title {
  font-family: "PingFang SC";
  font-size: 14px;
  font-weight: 500;
  color: #333333;
}

.preview-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 8px;
}

.preview-item {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 10px 12px;
  background: #ffffff;
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  transition: all 0.2s ease;

  &:hover {
    border-color: #07C05F;
    box-shadow: 0 2px 4px rgba(7, 192, 95, 0.08);
  }
}

.preview-index {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, #07C05F 0%, #05a04f 100%);
  color: #ffffff;
  border-radius: 4px;
  font-family: "PingFang SC";
  font-size: 12px;
  font-weight: 600;
}

.preview-question {
  flex: 1;
  font-family: "PingFang SC";
  font-size: 13px;
  color: #333333;
  line-height: 1.5;
  word-break: break-word;
}

.preview-more {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid #e5e7eb;
  font-family: "PingFang SC";
  font-size: 12px;
  color: #666666;
  text-align: center;
}

// 响应式布局由 JavaScript 动态计算，这里不需要媒体查询

// 卡片菜单弹窗样式
:deep(.faq-card-popup) {
  z-index: 99 !important;

  .t-popup__content {
    padding: 4px 0 !important;
    margin-top: 4px !important;
    min-width: 120px;
  }
}

// FAQ 编辑器抽屉样式
:deep(.faq-editor-drawer) {
  .t-drawer__body {
    padding: 20px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    height: 100%;
  }

  .t-drawer__header {
    padding: 20px 24px;
    border-bottom: 1px solid #e5e5e5;
    font-family: "PingFang SC";
    font-size: 18px;
    font-weight: 600;
    color: #000000e6;
  }

  .t-drawer__footer {
    padding: 16px 24px;
    border-top: 1px solid #e5e5e5;
  }
}

.faq-editor-drawer-content {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  min-height: 0;
  
  // 自定义滚动条
  &::-webkit-scrollbar {
    width: 6px;
  }

  &::-webkit-scrollbar-track {
    background: #f5f5f5;
    border-radius: 3px;
  }

  &::-webkit-scrollbar-thumb {
    background: #d0d0d0;
    border-radius: 3px;
    transition: background 0.2s;

    &:hover {
      background: #07C05F;
    }
  }

  .editor-form {
    width: 100%;
  }
}

.faq-editor-drawer-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}

// 全宽输入框包装器 - 统一样式
.full-width-input-wrapper {
  display: flex;
  gap: 8px;
  align-items: center;
  width: 100%;

  .full-width-input {
    flex: 1;
    min-width: 0;
  }

  .full-width-textarea {
    flex: 1;
    min-width: 0;
    
    :deep(.t-textarea__inner) {
      min-height: 80px;
    }
  }

  // textarea需要顶部对齐
  &.textarea-wrapper {
    align-items: flex-start;
  }

  .add-item-btn {
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    min-width: 32px;
    padding: 0;
    font-family: "PingFang SC";
    transition: all 0.2s ease;
    border-radius: 8px;
  }

  :deep(.add-item-btn) {
    background: #07C05F !important;
    border: 1px solid #07C05F !important;
    border-radius: 8px !important;
    color: #ffffff !important;
    display: flex;
    align-items: center;
    justify-content: center;

    &:hover:not(:disabled) {
      background: #05a04f !important;
      border-color: #05a04f !important;
      transform: scale(1.05);
      box-shadow: 0 2px 8px rgba(7, 192, 95, 0.3);
    }

    &:active:not(:disabled) {
      background: #048a42 !important;
      border-color: #048a42 !important;
      transform: scale(0.98);
    }

    &:disabled {
      background: #E5E7EB !important;
      border-color: #E5E7EB !important;
      color: #9CA3AF !important;
      cursor: not-allowed;
      opacity: 0.6;
    }

    .t-icon {
      font-size: 16px;
    }
  }
}

.textarea-container {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
}

.item-count {
  font-size: 13px;
  color: #6B7280;
  font-family: "PingFang SC";
  font-weight: 500;
  text-align: right;
  padding-right: 40px;
  line-height: 1;
}

.item-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
  margin-top: 8px;
}


.item-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  background: #ffffff;
  border: 1px solid #E7E7E7;
  border-radius: 8px;
  transition: all 0.2s ease;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
  position: relative;

  &.answer-row {
    align-items: flex-start;
    padding: 12px 14px;
  }

  &:hover {
    background: #fafafa;
    border-color: #07C05F;
    box-shadow: 0 2px 8px rgba(7, 192, 95, 0.12);
    transform: translateY(-1px);
  }

  &.negative {
    background: #FFFBEB;
    border-color: #FDE68A;

    &:hover {
      background: #FEF3C7;
      border-color: #FCD34D;
      box-shadow: 0 2px 8px rgba(251, 191, 36, 0.15);
    }
  }

  .item-content {
    flex: 1;
    font-size: 14px;
    line-height: 1.6;
    color: #111827;
    font-family: "PingFang SC";
    white-space: pre-wrap;
    word-break: break-word;
    padding: 0;
    font-weight: 400;
  }

  .remove-item-btn {
    flex-shrink: 0;
    color: #9CA3AF;
    padding: 0;
    width: 24px;
    height: 24px;
    min-width: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 6px;
    transition: all 0.2s ease;
    background: transparent;
    border: none;
    cursor: pointer;

    &:hover {
      color: #EF4444;
      background: #FEE2E2;
    }

    &:active {
      background: #FECACA;
    }

    :deep(.t-icon) {
      font-size: 14px;
    }
  }

  &.answer-row .remove-item-btn {
    margin-top: 0;
  }
}

.form-tip {
  margin-top: 6px;
  font-size: 12px;
  color: #00000066;
  font-family: "PingFang SC";
}

// FAQ编辑器表单样式 - 完全参考设置页面
.faq-editor-form {
  width: 100%;

  // 隐藏Form的默认结构
  :deep(.t-form__label) {
    display: none !important;
    width: 0 !important;
    padding: 0 !important;
    margin: 0 !important;
  }

  :deep(.t-form__controls) {
    margin-left: 0 !important;
    width: 100% !important;
  }

  :deep(.t-form__controls-content) {
    margin: 0 !important;
    padding: 0 !important;
    width: 100% !important;
    display: block !important;
  }

  :deep(.t-form-item) {
    margin-bottom: 0 !important;
    padding: 0 !important;
  }
}

.settings-group {
  display: flex;
  flex-direction: column;
  gap: 0;
}

.setting-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  padding: 20px 0;
  border-bottom: 1px solid #e5e7eb;

  &:last-child {
    border-bottom: none;
  }

  &.vertical {
    flex-direction: column;
    gap: 12px;

    .setting-control {
      width: 100%;
      max-width: 100%;
    }
  }

  // 主要字段（标准问、答案）的强调样式
  &.setting-row-primary {
    padding: 20px 0;
    padding-left: 12px;
    position: relative;

    // 第一个（标准问）去掉顶部间距
    &:first-child {
      padding-top: 0;
    }

    // 左侧颜色标记（标准问和答案都用绿色）
    &::before {
      content: '';
      position: absolute;
      left: 0;
      top: 20px;
      width: 3px;
      height: calc(100% - 40px);
      background: #07C05F;
      border-radius: 0 2px 2px 0;
    }

    &:first-child::before {
      top: 0;
      height: calc(100% - 20px);
    }
  }

  // 可选字段（相似问、反例）的次要样式
  &.setting-row-optional {
    padding-left: 12px;
    position: relative;

    // 左侧颜色标记
    &::before {
      content: '';
      position: absolute;
      left: 0;
      top: 20px;
      width: 3px;
      height: calc(100% - 40px);
      border-radius: 0 2px 2px 0;
    }

    .setting-info {
      .optional-label {
        color: #333333;
        font-weight: 500;
      }

      .optional-desc {
        color: #666666;
      }
    }
  }

  // 相似问的蓝色标记
  &.setting-row-similar::before {
    background: #3B82F6;
  }

  // 反例的橙色标记
  &.setting-row-negative::before {
    background: #F59E0B;
  }

  // 答案去掉底部边框
  &.setting-row-answer {
    border-bottom: none;
  }
}

.setting-info {
  flex: 1;
  max-width: 65%;
  padding-right: 24px;

  label {
    font-size: 15px;
    font-weight: 500;
    color: #333333;
    display: block;
    margin-bottom: 4px;
  }

  .required-label {
    font-size: 15px;
    font-weight: 600;
    color: #333333;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-bottom: 4px;
  }

  .required-mark {
    color: #FA5151;
    font-weight: 600;
    font-size: 14px;
  }

  .optional-label {
    font-size: 15px;
    font-weight: 600;
    color: #333333;
    display: block;
    margin-bottom: 4px;
  }

  .desc {
    font-size: 13px;
    color: #666666;
    margin: 0;
    line-height: 1.5;
  }

  .optional-desc {
    font-size: 13px;
    color: #666666;
  }
}

.setting-row.vertical .setting-info {
  max-width: 100%;
  padding-right: 0;
  width: 100%;
}

.setting-control {
  flex-shrink: 0;
  min-width: 280px;
  display: flex;
  justify-content: flex-end;
  align-items: center;
}

.setting-row.vertical .setting-control {
  width: 100%;
  max-width: 100%;
  min-width: unset;
  justify-content: flex-start;
  align-items: flex-start;
  flex-direction: column;
}

// 垂直布局中的输入框确保全宽
.setting-row.vertical .full-width-input {
  width: 100%;

  :deep(.t-input__wrap) {
    width: 100%;
  }
}

.setting-row.vertical .full-width-textarea {
  width: 100%;

  :deep(.t-textarea) {
    width: 100%;
  }
}

// Input 组件样式 - 与登录页面一致
:deep(.t-input) {
  font-family: "PingFang SC";
  font-size: 14px;
  border: 1px solid #E7E7E7;
  border-radius: 8px;
  background: #fff;
  transition: all 0.2s ease;

  &:hover {
    border-color: #07C05F;
  }

  &:focus-within {
    border-color: #07C05F;
    box-shadow: 0 0 0 3px rgba(7, 192, 95, 0.1);
  }

  .t-input__inner {
    border: none !important;
    box-shadow: none !important;
    outline: none !important;
    background: transparent;
    font-size: 14px;
    font-family: "PingFang SC";
    padding: 6px 12px;
    color: #111827;

    &:focus {
      border: none !important;
      box-shadow: none !important;
      outline: none !important;
    }

    &::placeholder {
      color: #9CA3AF;
    }
  }

  .t-input__wrap {
    border: none !important;
    box-shadow: none !important;
  }
}

// Textarea 组件样式
:deep(.t-textarea) {
  font-family: "PingFang SC";
  font-size: 14px;
  border: 1px solid #E7E7E7;
  border-radius: 8px;
  background: #fff;
  transition: all 0.2s ease;

  &:hover {
    border-color: #07C05F;
  }

  &:focus-within {
    border-color: #07C05F;
    box-shadow: 0 0 0 3px rgba(7, 192, 95, 0.1);
  }

  .t-textarea__inner {
    border: none !important;
    box-shadow: none !important;
    outline: none !important;
    background: transparent;
    font-size: 14px;
    font-family: "PingFang SC";
    line-height: 1.6;
    resize: vertical;
    padding: 6px 12px;
    color: #111827;

    &:focus {
      border: none !important;
      box-shadow: none !important;
      outline: none !important;
    }

    &::placeholder {
      color: #9CA3AF;
    }
  }
}

:deep(.t-button--theme-primary) {
  background-color: #07c05f;
  border-color: #07c05f;
  
  &:hover {
    background-color: #05a04f;
    border-color: #05a04f;
  }
}

// 导入弹窗动画
.modal-enter-active,
.modal-leave-active {
  transition: opacity 0.2s ease;
}

.modal-enter-active .faq-import-modal,
.modal-leave-active .faq-import-modal,
.modal-enter-active .batch-tag-modal,
.modal-leave-active .batch-tag-modal {
  transition: transform 0.2s ease, opacity 0.2s ease;
}

.modal-enter-from,
.modal-leave-to {
  opacity: 0;
}

.modal-enter-from .faq-import-modal,
.modal-leave-to .faq-import-modal,
.modal-enter-from .batch-tag-modal,
.modal-leave-to .batch-tag-modal {
  transform: scale(0.95);
  opacity: 0;
}

// Tag 样式优化
.answer-tag {
  background: #07c05f1a;
  color: #07c05f;
  border-color: #07c05f33;
}

.question-tag {
  background: #fff;
  border-color: #d9d9d9;
  color: #00000099;
}

// Search test drawer styles - 与编辑器抽屉风格一致
:deep(.faq-search-drawer) {
  .t-drawer__body {
    padding: 20px;
    display: flex;
    flex-direction: column;
    height: 100%;
  }

  .t-drawer__header {
    padding: 20px 24px;
    border-bottom: 1px solid #e5e5e5;
    font-family: "PingFang SC";
    font-size: 18px;
    font-weight: 600;
    color: #000000e6;
  }
}

.search-test-content {
  display: flex;
  flex-direction: column;
  gap: 16px;
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding-right: 0;

  // 隐藏滚动条但保持滚动功能
  scrollbar-width: none; // Firefox
  -ms-overflow-style: none; // IE and Edge

  &::-webkit-scrollbar {
    display: none; // Chrome, Safari, Opera
  }
}

.search-form {
  flex-shrink: 0;

  :deep(.t-form__label) {
    display: none !important;
    width: 0 !important;
    padding: 0 !important;
    margin: 0 !important;
  }

  :deep(.t-form__controls) {
    margin-left: 0 !important;
    width: 100% !important;
  }

  :deep(.t-form__controls-content) {
    margin: 0 !important;
    padding: 0 !important;
    width: 100% !important;
    display: block !important;
  }

  :deep(.t-form-item) {
    margin-bottom: 0 !important;
    padding: 0 !important;
  }
}

.slider-wrapper {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 2px 0;
}

.search-form .setting-row {
  padding: 16px 0;
  border-bottom: 1px solid #e5e7eb;

  &.search-first-row {
    padding-top: 0;
  }

  &:last-child {
    border-bottom: none;
    padding-bottom: 0;
  }

  .setting-info {
    max-width: 100%;
    padding-right: 0;
    margin-bottom: 8px;

    label {
      font-size: 14px;
      font-weight: 500;
      color: #333333;
      display: block;
      margin-bottom: 4px;
    }

    .desc {
      font-size: 12px;
      color: #666666;
      margin: 0;
      line-height: 1.4;
    }
  }

  .setting-control {
    width: 100%;
    max-width: 100%;
    min-width: unset;
    justify-content: flex-start;
    align-items: flex-start;
    flex-direction: column;
  }
}

:deep(.slider-wrapper .t-slider) {
  flex: 1;
  min-width: 0;

  .t-slider__rail {
    background: #E7E7E7;
    height: 4px;
    border-radius: 2px;
  }

  .t-slider__track {
    background: #07C05F;
    height: 4px;
    border-radius: 2px;
  }

  .t-slider__button {
    width: 16px;
    height: 16px;
    border: 2px solid #07C05F;
    background: #ffffff;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);

    &:hover {
      border-color: #05a04f;
      box-shadow: 0 2px 8px rgba(7, 192, 95, 0.2);
    }
  }
}

.slider-value {
  flex-shrink: 0;
  min-width: 50px;
  text-align: right;
  font-family: "PingFang SC";
  font-size: 14px;
  font-weight: 500;
  color: #111827;
  padding: 4px 8px;
  background: #F9FAFB;
  border-radius: 6px;
}

.search-button {
  height: 36px;
  border-radius: 8px;
  font-family: "PingFang SC";
  font-size: 14px;
  font-weight: 500;
  transition: all 0.2s ease;

  &:hover:not(:disabled) {
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(7, 192, 95, 0.3);
  }

  &:active:not(:disabled) {
    transform: translateY(0);
  }
}

.search-results {
  display: flex;
  flex-direction: column;
  padding-top: 20px;
  padding-left: 0;
  width: 100%;
  box-sizing: border-box;
}

.results-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 16px;
  margin-left: 0;
  margin-right: 0;
  padding-left: 0;
  font-family: "PingFang SC";
  font-size: 14px;
  font-weight: 600;
  color: #111827;
  flex-shrink: 0;
  justify-content: flex-start;

  .t-icon {
    color: #07C05F;
  }
}

.no-results {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 48px 16px;
  color: #6B7280;
  font-family: "PingFang SC";
  font-size: 14px;
  text-align: center;
  background: #F9FAFB;
  border-radius: 8px;
  border: 1px dashed #E7E7E7;
}

.results-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.result-card {
  border: 1px solid #E7E7E7;
  border-radius: 8px;
  background: #fff;
  padding: 14px;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
  width: 100%;
  box-sizing: border-box;
  min-width: 0;
  overflow: visible;
  position: relative;

  &:hover {
    border-color: #07C05F;
    box-shadow: 0 2px 8px rgba(7, 192, 95, 0.12);
  }
}

.result-header {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 0;
  border-bottom: none;
  cursor: pointer;
  user-select: none;
  padding: 4px;
  margin: -4px;
  border-radius: 6px;
  position: relative;

  &:hover {
    background-color: #F9FAFB;
  }
}

.result-card.expanded .result-header {
  margin-bottom: 12px;
  padding-bottom: 12px;
  border-bottom: 1px solid #E7E7E7;
  margin-left: -4px;
  margin-right: -4px;
  padding-left: 4px;
  padding-right: 4px;
}

.result-question-wrapper {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
}

.result-question {
  flex: 1;
  min-width: 0;
  font-family: "PingFang SC";
  font-size: 14px;
  font-weight: 600;
  color: #111827;
  line-height: 1.6;
  word-break: break-word;
  display: flex;
  align-items: flex-start;
  gap: 6px;

  .result-index {
    flex-shrink: 0;
    color: #07C05F;
    font-weight: 600;
  }
}

.result-meta {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  flex-shrink: 0;
  margin-left: auto;
}

.expand-icon {
  flex-shrink: 0;
  font-size: 18px;
  color: #6B7280;
  transition: transform 0.2s ease;
  cursor: pointer;

  &:hover {
    color: #07C05F;
  }
}

.score-tag,
.match-type-tag {
  font-size: 12px;
  padding: 4px 8px;
  border-radius: 6px;
  font-family: "PingFang SC";
}

.result-body {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-top: 12px;
  margin-top: 0;
  border-top: 1px solid #F3F4F6;
  position: relative;
  width: 100%;
}

// Slide down animation - 优化性能
.slide-down-enter-active {
  transition: opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1), 
              transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  overflow: hidden;
  will-change: opacity, transform;
}

.slide-down-leave-active {
  transition: opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1), 
              transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  overflow: hidden;
  will-change: opacity, transform;
}

.slide-down-enter-from {
  opacity: 0;
  transform: translateY(-8px);
}

.slide-down-enter-to {
  opacity: 1;
  transform: translateY(0);
}

.slide-down-leave-from {
  opacity: 1;
  transform: translateY(0);
}

.slide-down-leave-to {
  opacity: 0;
  transform: translateY(-8px);
}

.result-section {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

// 批量分类弹窗样式 - 与导入对话框风格一致
.batch-tag-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  backdrop-filter: blur(4px);
}

.batch-tag-modal {
  position: relative;
  width: 100%;
  max-width: 480px;
  background: #ffffff;
  border-radius: 12px;
  box-shadow: 0 6px 28px rgba(15, 23, 42, 0.08);
  overflow: hidden;
  display: flex;
  flex-direction: column;

  .batch-tag-close-btn {
    position: absolute;
    top: 20px;
    right: 20px;
    width: 32px;
    height: 32px;
    border: none;
    background: #f5f5f5;
    border-radius: 6px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #666;
    transition: all 0.2s ease;
    z-index: 10;

    &:hover {
      background: #e5e5e5;
      color: #000;
    }
  }
}

.batch-tag-container {
  display: flex;
  flex-direction: column;
  padding: 24px;
}

.batch-tag-header {
  margin-bottom: 24px;
  padding-right: 40px;

  .batch-tag-title {
    margin: 0;
    font-size: 20px;
    font-weight: 600;
    color: #0f172a;
    line-height: 1.4;
  }
}

.batch-tag-content {
  flex: 1;
  min-height: 0;
}

.batch-tag-tip {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 12px 16px;
  margin-bottom: 20px;
  background: #f0f9ff;
  border: 1px solid #bae6fd;
  border-radius: 8px;
  font-size: 14px;
  color: #0369a1;
  line-height: 1.5;

  .tip-icon {
    flex-shrink: 0;
    margin-top: 2px;
    color: #0284c7;
  }
}

.batch-tag-form {
  margin-top: 0;

  :deep(.t-form-item) {
    margin-bottom: 0;
  }

  :deep(.t-form-item__label) {
    font-size: 14px;
    font-weight: 500;
    color: #1d2129;
    margin-bottom: 8px;
  }
}

.batch-tag-select {
  width: 100%;
}

.batch-tag-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px solid #e5e7eb;
}

.tag-select-empty {
  padding: 8px 12px;
  text-align: center;
  color: #86909c;
  font-size: 14px;
}

.section-label {
  font-family: "PingFang SC";
  font-size: 12px;
  font-weight: 600;
  color: #6B7280;
  margin-bottom: 4px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.result-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  width: 100%;
  min-width: 0;
}

:deep(.result-tags .t-tag) {
  max-width: 100%;
  min-width: 0;
  word-break: break-word;
  overflow-wrap: break-word;
}

:deep(.result-tags .t-tag__text) {
  display: inline-block;
  max-width: 100%;
  word-break: break-word;
  overflow-wrap: break-word;
  white-space: normal;
  line-height: 1.4;
}
</style>



